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

David Chelimsky dchelimsky at gmail.com
Fri Sep 30 17:42:31 EDT 2011


On Sep 30, 2011, at 4:32 PM, Srushti Ambekallu wrote:

> 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

That's one of the benefits of let :) You can use it to declare objects but they only get instantiated when you reference them.

See https://www.relishapp.com/rspec/rspec-core/docs/helper-methods/let-and-let



More information about the rspec-users mailing list