Unavoidable let - RSpec
While pairing with Steph, who was helping me improve a spec file, I was asking
how I could get rid of the top level let.
The file before was:
describe FooSerializer do
context "foo serializer something something" do
let(:model) { FactoryBot.create(:foo, :with_bar_trait) }
subject { described_class.new(model) }
it_behaves_like "a serialized model with status"
it "has a name attribute" do
expect(subject.attributes[:name]).to eq(model.name)
end
it "has a phone attribute" do
expect(subject.attributes[:phone]).to eq(model.phone)
end
[etc etc for many attributes]
end
end
After refactoring it looked like this:
describe FooSerializer do
it_behaves_like "a serialized model with status" do
let(:model) { FactoryBot.build(:foo, :with_bar_trait) }
subject { described_class.new(model) }
end
it "has foo attributes" do
model = FactoryBot.build(:foo, :with_bar_trait)
subject = described_class.new(model)
expect(subject.attributes[:name]).to eq(model.name)
expect(subject.attributes[:phone]).to eq(model.phone)
[etc etc all the attributes grouped here]
end
end
1) Grouping the long list of attributes was beneficial and we could call the
model only once in the it.
2) We successfully used build instead of create everywhere in the file.
3) The top level let was unavoidable because it_behaves_like, which came from the
shared_examples, needs to have the let specified when passed as a block.
From Stack Overflow:
let(:data) { "saved data" }
shared_examples "saves data to right place" do
it { expect(right_place.data).to eq data }
end
context "when something it saves to one place" do
it_behaves_like "saves data to right place" do
let(:right_place) { create(:place) }
end
end
context "when whatever it saves to other place" do
it_behaves_like "saves data to right place" do
let(:right_place) { create(:place) }
end
end