Say I have a method MyKlass#do_thing
that I want to call exactly once in a test (because it might change a state), and that should return true
on successful state change and false
otherwise. I want to write a spec that looks something like this:
it "Updates myvalue if condition is met" do
wojit = MyKlass.new
# ... assuming condition is met
expect { wojit.do_thing }.to change { wojit.value }.and.be true
end
But this particular approach gets an ArgumentError, because #and
expects 1 argument.
I can make it work with the following abomination:
expect { expect(wojit.do_thing).to be true }.to change { wojit.value }
But that is hiiiiideous. Am I missing something more idiomatic?
This question is 6y old but still relevant, so I wanted to update with latest preferred solution for this problem.
subject
evaluation is cached. This allows you first check the change effect, and on the next line check return value without it running twice. Basically same as @rampion suggested just more readable.
subject(:do_thing) { wojit.do_thing }
let(:wojit) { MyKlass.new }
it "changes and returns true" do
expect{ do_thing }.to change(wojit, :value)
expect( do_thing ).to be(true)
end