[rspec-users] let vs ivar w/ before block

Srushti Ambekallu srushti at ambekallu.com
Fri Sep 30 17:32:25 EDT 2011


On 30/09/11 3:58 PM, David Chelimsky wrote:
> On Sep 30, 2011, at 3:31 PM, Patrick J. Collins wrote:
>
>>> Proper usage, sure, but the memoization is only within each example - not across examples. That way you can do this:
>>>
>>> let(:thing) { Thing.new }
>>>
>>> it "does something" do
>>>   thing.blah
>>>   thing.whatever
>>>   thing.yet_again
>>> end
>>>
>>> In that case each reference to thing returns the same object.
>>>
>>> Make sense?
>> Hmm.. now I am confused...
>>
>> What is the difference between:
>>
>> describe "Foo" do
>>
>>   let(:foo) { Foo.new }
>>
>>   it "is tubular" do
>>     foo.bar
>>     foo.baz
>>   end
>>
>>   it "is gnarly" do
>>     foo.gnarl
>>     foo.wurd_up
>>   end
>>
>> end
>>
>> vs.
>>
>> describe "Foo" do
>>
>>   before :each do
>>     @foo = Foo.new
>>   end
>>
>>   it "seems just as tubular as the foo w/ let" do
>>     @foo.bar
>>     @foo.baz
>>   end
>>
>>   it "seems just as gnarly as the foo w/ let" do
>>     @foo.gnarl
>>     @foo.wurd_up
>>   end
>>
>> end
>>
>> I am not seeing any difference...?
> There is not, really, other than how the declaration of foo is expressed and referenced. This evolved out of a common pattern in TDD:
>
> 1:
>
> describe "something" do
>    it "does something" do
>      thing = Thing.new
>      thing.do_something.should have_some_outcome
>    end
> end
>
> 2:
>
> describe "something" do
>    it "does something" do
>      thing = Thing.new
>      thing.do_something.should have_some_outcome
>    end
>
>    it "does something else" do
>      thing = Thing.new
>      thing.do_something_else.should have_some_other_outcome
>    end
> end
>
> Now there is duplication so we can refactor out the declaration of thing. It takes less work and is less error prone to change it to a let declaration than to change the references to thing to an instance variable declared in a before hook.
>
> Cheers,
> David
>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>
One thing I noticed, and something that always catches me out is the 
fact that the 'let'ted object doesn't get instantiated until it gets 
referenced. Therefore,

describe "all" do
     let(:foo) { Foo.create! }

     it "returns the created object" do
         Foo.all.should include(foo)
     end
end

... fails, since at the time of calling :all, the 'foo' object hasn't 
been referred yet, and hence the block hasn't executed. "Foo.all" in the 
case above returns an empty array, which wouldn't have been the case 
with an instance object created in "before(:each)".

Srushti
http://c42.in


More information about the rspec-users mailing list