let()’s write slightly cleaner specs

Published on and tagged with bdd  rspec

When writing specs for your code, you often have to do some initialization. With RSpec I do this initialization in a “before” block as shown in the following example:

describe BlogPost do
  before do
    @blog_post = BlogPost.create :title => 'Hello'
  end

  it "does something" do
    @blog_post.should ...
  end

  it "does something else" do
    @blog_post.should ...
  end
end

However, recently I stumbled upon a cleaner approach in a presentation (from which I borrowed the examples in this article) by Jon Larkowski that makes use of RSpec’s let() method. With this approach, the example from above looks like:

describe BlogPost do
  let(:blog_post) { BlogPost.create :title => 'Hello' }

  it "does something" do
    blog_post.should ...
  end

  it "does something else" do
    blog_post.should ...
  end
end

At first this looked quite magic to me and I had no clue how it worked. Though a look at the source of the let() method reveals the magic (the code should be self-explanatory, or else please leave a comment):

def let(name, &block)
  define_method name do
    @assignments ||= {}
    @assignments[name] ||= instance_eval(&block)
  end
end

Happy RSpecing!

© daniel hofstetter. Licensed under a Creative Commons License