Tuesday, October 16, 2012

Mocks: A Guest Post by Zach Lloyd

So, you wrote a test that uses mocks where you could have used real dependencies...

I have a few major issues with this style of test:

  • It tests implementation, not behavior.  Why should a test care what methods are called within a function being tested so long as the function behaves in accordance with its contract?  With these kinds of tests it’s often possible to change a function to use a completely equivalent implementation, and yet the test fails after the change.  In the extreme, test cases like this end up purely mimicking the implementation of the method under test (e.g. if the method being tested calls x(), y(), z() on its dependency, then you will see that exact same sequence of calls in the mock setup).  This ends up testing nothing at all.
  • You can't even write a test with mocks like this without looking into the implementation of the class under test, which adds a lot of complexity to test writing and maintenance.
  • It takes me a non-trivial amount of mental effort to read one of these test cases with mocks -- much more than reading regular code.
  • I've never believed the argument that it's somehow bad to test real code.  Unless the dependency is truly on something that's hard to test reliably (like a network), I think you absolutely should be testing the real dependency by default.  I know the testing people disagree with this, but I don't particularly care.  The tests should be on an environment as similar to the real application as possible IMO.

I do feel pretty strongly that tests that use mocks like this are bad, but I'll leave it up to you whether you want to change it.

No comments:

Post a Comment