I've been really loving using contexts
, subjects
and its
with rspec to really clean up my test code. Typical example:
context "as a user" do
subject{ Factory :user }
its(:name){ should == "Bob" }
end
What I can't figure out though is how I could make this condition dynamic (ie. based on other objects). its
appears to instance eval the attribute within the block so I lose access to everything around it. I'd love to do something like:
its(:name){ should == subject.contact.name }
But I can't see any way of achieving this. Does anyone know if there is some a method proxied through to this instance eval that gives access to the origin object? Or if there's any other way I can use methods outside the scope of the instance of the attribute that I'm checking?
It seems as if subject
within the its
block gets changed to the actual attribute (name
in this case)
Interestingly, I have access to any of my let
methods, but again, I don't have access to my original subject
in question.
You are almost answering yourself, use a let
assignment before you set the subject. Then you can reference it everywhere:
context "as a user" do
let(:user) { Factory(:user) }
subject { user }
its(:name) { should == user.contact.name }
end
I'm a context
, subject
, its
lover too !
Not sure if there's a way to do exactly what you're asking for since the "subject" within the block becomes the return value of User#name
.
Instead, I've used the let
method along with the following spec style to write this kind of test:
describe User do
describe '#name' do
let(:contact) { Factory(:contact, name: 'Bob') }
let(:user) { Factory(:user, contact: contact) }
subject { user.name }
it { should == 'Bob' }
end
end
This of course makes some assumptions about what your contact represents (here it's an association or similar). You may also choose to stub the return value of User#contact
instead of relying on FactoryGirl to set up a "real" association.
Regardless of the choices you make on those fronts, this strategy has worked well for me. I find it allows me to be more concise about what is under test, while preserving info (for other devs & future self) about where the expected return value is coming from.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With