The RSpec subject functionality can be useful for simplifying your spec setup and getting straight to the point. I really like using an explicit subject because it helps describe what functionality is under test when you’re writing your specs. Recently, I learned it was possible to nest your subject when using a named subject.
The subject
syntax allows you to use the one-liner syntax for writing a test which can really clean up a spec file. Let’s take a trivial example of a Rails model:
describe Car do
let(:car) { Car.new }
it "is a vehicle" do
expect(car).to be_a(Vehicle)
end
end
For this trivial case, you’ll notice that our expectation pretty literally matches the description of the test case. This might be a good use case for subject
:
describe Car do
subject { Car.new }
it { is_expected.to be_a(Vehicle) }
end
The above will test the same functionality and also leave pretty similar spec output when the spec is run.
You can also redefine your subject
for different blocks of your test. Let’s set the subject
for an instance method that I want to test:
describe Car do
subject { Car.new }
it { is_expected.to be_a(Vehicle) }
describe "#parked?" do
subject { Car.new.parked? }
it { is_expected.to eq(false) }
end
end
Dope. By redefining the subject
we can use the one-line syntax wherever we want.
The final trick is we can add an name to our initial subject
so we can reference it later within the spec:
describe Car do
subject(:car) { Car.new }
it { is_expected.to be_a(Vehicle) }
describe "#parked?" do
subject { car.parked? }
it { is_expected.to eq(false) }
end
end
I find this particularly useful if the subject
in the enclosing block has some complex setup:
describe Car do
let(:driver) { Person.new }
let(:front_seat) { Person.new }
subject(:car) { Car.new(driver: driver, front_seat: front_seat) }
it { is_expected.to be_a(Vehicle) }
describe "#parked?" do
subject { car.parked? }
it { is_expected.to eq(false) }
end
end
Now we can leverage any earlier setup while still having the benefits of different subjects in each context.
Shout out to Zack Mariscal for helping me edit and improve this post and my writing in general.
Top comments (0)