I’m watching Francis Hwang’s talk from RubyConf 2008 titled “Testing Heresies.” He discusses his reasons for not using mock objects, and commits a common error when trashing mocks: he shows crappy examples which evidently serve as proof of why the technique sucks.
To start, let’s look at the two main arguments people make for why mocks suck:
- They duplicate the code under test
- Objects can get out of sync when interfaces change
Here’s a code example Francis gives that uses mocks:
Before he gets into it, he says something along the lines of “Please let me know if I’m mischaracterizing the approach.” Too bad I wasn’t there. Yes, you COMPLETELY mischaracterized the approach.
If you’re using mocks like this, you’re doing it wrong. Very, very wrong. Here’s how you would really use mocks:
Then you would have a model level spec:
This is one example where I’ll cave in to the whole “mocks duplicate the code under test” argument. If your mocking code sucks, and your mocking code duplicates your production code, then guess what? Your production code sucks!
The value that mocking provides in this case is writing the code you wish you had. Do you really wish you had a find(:select => …, :conditions => …) in your controller code? Of course not! (I hope not, anyway). You don’t have to use mocks to get the APIs you want (refactoring is still an option but it’s very, very helpful.
Bottom line: mocks aren’t inherently evil. I could take Francis’s example as proof of why Ruby, Rails, and RSpec all suck, and it would be just as valid as concluding that mocks suck. The only things that sucked here are the example and the production code.
Code gets out of sync
No it doesn’t. Let me give you a very quick rundown of the code you would write to implement this feature.
1. Write a cucumber feature
2. Write the controller spec, mocking out the finder, implement controller
3. Write model specs for the finder, implement finder
Now when someone says “but if I rename the finder, the controller spec will continue to pass! Mocks are horrible!!” You can point to the acceptance test that fails. Holy quality software, batman!