Ripping out your mocks
Courtenay : November 6th, 2008
I sat down with David Chelimsky at Rubyconf today to talk about rSpec and an interesting topic came up.
In my mind, there are two reasons to use a mock object: first, when you’re developing TDD style, you physically don’t have the objects yet; and second, so that you can tightly focus your unit tests. Maybe, these two different purposes should use a different mechanism.
His question to me then was, “Do you replace your mocks with the real objects after you’ve implemented those objects?”. I guess I hadn’t thought about that before. Do you? If so, how do you handle the extra complexity, maintaining sane associations and valid data?
8 Responses to “Ripping out your mocks”
Sorry, comments are closed for this article.
November 6th, 2008 at 01:01 PM
The idea is that you use mocking to discover an API/object. After you've specced how should be interacted with a mock, you could replace the mock with a real object.
Using real objects make tests less brittle, but have the disadvantage of requiring a bit of more 'setup' code.
I agree on the following:"how do you handle the extra complexity, maintaining sane associations and valid data?", but using mocks all over the place will make maintaining valid mocks hard without good application level tests. And if you have really good application level tests that work without mocks, do you really need all those additional unit test using mocks?
November 6th, 2008 at 01:33 PM
Are you guys still not using Rspec anymore?
We have been on the brink from moving from Test:Unit for about a year and a half but not got round to it. Are there any another decent options out there?
November 6th, 2008 at 08:37 PM
Synthesis proposes a solution to this problem: http://synthesis.rubyforge.org/
Basically they say that you don't need to substitute with your real objects if you can check that each mock you use has a test with the real object that backs it up.
So if for example I have a mock like this somewhere:
Synthesis verifies that a unit test exercising Greeter.greet(:english) exists.
November 6th, 2008 at 08:58 PM
... I know, I know, that's a stub not a mock
November 7th, 2008 at 08:51 PM
If you don't have your objects yet... shouldn't your tests fail? Isn't that the point of test first development? You write a failing test, then do the minimal possible to make it pass?
November 9th, 2008 at 05:26 PM
Justin - there are times when the object you're focused on right now needs help from some collaborator that doesn't exist yet. For you to build out that collaborator first would take your focus from the object you're focused on now.
Enter mock objects.
Mocks as a TDD aid keep focused on the object at hand, while simultaneously discovering the interfaces of its collaborators.
November 9th, 2008 at 06:24 PM
Daniel - Synthesis seems like a cool idea, but unfortunately it only works with methods that are actually defined on a class - not so much with those that are added by extending objects at runtime: "http://gist.github.com/23406":http://gist.github.com/23406
Still might be useful for some cases.
November 24th, 2008 at 05:28 AM
I think mock objects must be backed up with real objects when they become available. This is the only way you can test the object behavior vs. reality.
I see mocking very helpful when testing different scenarios without using fixtures, ie. forcing an object to behave in a specific way when a specific scenario happens.