What is difference between let
and a before
block in RSpec?
And when to use each?
What will be good approach (let or before) in below example?
let(:user) { User.make !}
let(:account) {user.account.make!}
before(:each) do
@user = User.make!
@account = @user.account.make!
end
I studied this stackoverflow post
But is it good to define let for association stuff like above?
People seem to have explained some of the basic ways in which they differ, but left out before(:all)
and don't explain exactly why they should be used.
It's my belief that instance variables have no place being used in the vast majority of specs, partly due to the reasons mentioned in this answer, so I won't mention them as an option here.
let blocks
Code within a let
block is only executed when referenced, lazy loading this means that ordering of these blocks is irrelevant. This gives you a large amount of power to cut down on repeated setup through your specs.
One (extremely small and contrived) example of this is:
let(:person) { build(:person) }
subject(:result) { Library.calculate_awesome(person, has_moustache) }
context 'with a moustache' do
let(:has_moustache) { true }
its(:awesome?) { should be_true }
end
context 'without a moustache' do
let(:has_moustache) { false }
its(:awesome?) { should be_false }
end
You can see that has_moustache
is defined differently in each case, but there's no need to repeat the subject
definition. Something important to note is that the last let
block defined in the current context will be used. This is good for setting a default to be used for the majority of specs, which can be overwritten if needed.
For instance, checking the return value of calculate_awesome
if passed a person
model with top_hat
set to true, but no moustache would be:
context 'without a moustache but with a top hat' do
let(:has_moustache) { false }
let(:person) { build(:person, top_hat: true) }
its(:awesome?) { should be_true }
end
Another thing to note about let blocks, they should not be used if you're searching for something which has been saved to the database (i.e. Library.find_awesome_people(search_criteria)
) as they will not be saved to the database unless they have already been referenced. let!
or before
blocks are what should be used here.
Also, never ever