Say I have code like this:
class Car
def test_drive!; end
end
class AssemblyLine
def produce!
car = Car.new
car.test_drive!
end
end
Now, using RSpec I want to test/spec AssemblyLine without exercising Car as well. I hear we don’t do dependency injection in Ruby, we stub new instead:
describe AssemblyLine
before do
Car.stub(:new).and_return(double('Car'))
end
describe '#produce'
it 'test-drives new cars' do
the_new_instance_of_car.should_receive(:test_drive) # ???
AssemblyLine.new.produce!
end
end
end
The problem, as you can see, is with the_new_instance_of_car. It doesn’t exist yet before produce is called, and after produce returns it’s too late to set any method call expectations on it.
I can think of a workaround involving a callback in the stubbed new method, but that’s rather hideous. There must be a more elegant and idiomatic way to solve this seemingly common problem. Right…?
Update: here’s how I solved it.
describe AssemblyLine
def stub_new_car(&block)
Car.stub(:new) do
car = double('Car')
block.call(car) if block
car
end
end
before { stub_new_car } # to make other tests use the stub as well
describe '#produce'
it 'test-drives new cars' do
stub_new_car { |car| car.should_receive(:test_drive) }
AssemblyLine.new.produce!
end
end
end
You can set an expectation on the test double:
You can also call
any_instanceon the class (as of RSpec 2.7, I think):