In writing Rspec tests, I'm often frustrated with
should_receive. I'd like to know if there's a less intrusive alternative.
describe "making a cake" do it "should use some other methods" do @baker.should_receive(:make_batter) @baker.make_cake end end
La llamada a la
should_receive is a good description, but it breaks my code, because
should_receive works by masking the original method, and
make_cake can't proceed unless
make_batter actually returns some batter. So I change it to this:
This is ugly because:
- It miradas like I'm testing that
@batter, but I'm realmente forcing the fake version of
make_batterto return that.
- It forces me to separately set up
make_batterhas any important side effects (which could be a code smell, I suppose) I have to make those happen, too.
me gustaría que
should_receive(:make_batter) would verify the method call and pass it on to the original method. If I wanted to stub its behavior for better isolation testing, I would do so explicitly:
¿Hay alguna manera de hacer algo como
should_receive without preventing the original method call? Is my problem a symptom of bad design?
preguntado el 28 de agosto de 12 a las 13:08
It looks like the nicer API to delegate to the original method that Myron Marston alluded to has actually been added in rspec-mocks v2.12.0
So now you can simply do this any time you "want to set a message expecation without interfering with how the object responds to the message":
Thanks for adding this, Myron.
Tu puedes tener
should_receive run the original method like so:
stub support passing a block implementation (that is eval'd when the method is called).
&@baker.method(:make_batter) gets a handle to the original method object, and passes it along as the block implementation.
FWIW, we'd like to provide a nicer API to delegate to the original method (see este problema), but it's difficult to add that functionality without breaking backwards compatibility.
You're having this problem with
should_receive because you're testing implementation details of the
make_cake method. When writing tests you should only focus on behavior and not on a sequence of internal method calls. Otherwise refactoring your code later would result in a huge refactoring of all your tests as well.
Mocks and Stubs come in handy when you want to test your classes in isolation. When writing unit tests your test subject should be isolated from any other object. Both act as a stand-in when you're working with multiple objects at once. In this case you can use
should_receive to ensure that your test subject correctly delegates some task to another object by calling a method.