During development of a small Ruby application today I ran into a minor issue with RSpec and Mocha. Earlier today, I was developing a small Ruby application, trying out RSpec instead of the usual Test::Unit, using Mocha for my stubbing and mocking needs.
Unfortunately, things didn’t go as I expected them to today. Imagine starting out with the following (contrived) examples:
describe 'Car' do
describe "when starting" do
before :each do
@car = Car.new
end
it "should insert key" do
@car.expects(:insert_key)
@car.start
end
it "should turn key" do
@car.expects(:turn_key)
@car.start
end
end
end
That’s the behaviour I want, now let’s add some code to make the specs green.
class Car
def start
end
end
The above is a nice scaffold for our full implementation, but there is one problem. The specs actually pass! Without any actual code, the expectations are apparently being triggered. This is obviously not correct, and it was driving me mildly crazy. Fortunately, a bit of Googling led me to a blog post who gave me the solution.
While RSpec has its own, built-in mocking framework it doesn’t mind stepping down and leave the mocking to Mocha - but you have to tell it to do so:
Spec::Runner.configure do |config|
config.mock_with :mocha
end
With the above added to my specs they properly fail, yay! Hopefully that’ll teach me to RTFM.
Jakob, I really don't think it's a good idea to mock interactions within the same object. I usually only try to test the behaviour between objects. For example:
describe 'Car' do describe "when starting" do before :each do @key = Key.new (or mock if Key.new requires too much setup code) @car = Car.new(@key) end it "should insert key" do @key.expects(:insert) @car.start end it "should turn key" do @key.expects(:turn) @car.start end end endWhat do you think?
That got messed up pretty much, please see http://gist.github.com/10764.
Great you are doing BDD, Jakob.
I think coming up with bulletproof code examples is hard ;)
I am not entirely sure I agree with your point. Inter-object interaction should obviously be specced, but I don't see why intra-object interaction (intraaction?) shouldn't?
Anyways, it's all besides the point. Even with your code RSpec still needs to be told that it's using Mocha for stubbing as I mention above.