[Links] Mocks

Don’t Overuse Mocks

From Andrew Trenk, in the Google testing blog:

When writing tests for your code, it can seem easy to ignore your code's dependencies by mocking them out.

However, not using mocks can sometimes result in tests that are simpler and more useful.

If you're trying to read a test that uses mocks and find yourself mentally stepping through the code being tested in order to understand the test, then you're probably overusing mocks.

Sometimes you can't use a real dependency in a test (e.g. if it's too slow or talks over the network), but there may better options than using mocks

Stop Using Mocks

From Karl Seguin's blog:

In conclusion, by their very nature, mocks are all about testing interactions.

This doesn't decrease coupling like most think. There's actually no way to create greater coupling than to us a mock - because you have to specify every possible detail of each interaction.

When you want to test interactions, which you should test, use a mock. But I guarantee you that the ratio of behavioral tests to interaction tests will be in the neighborhood of 5 to 1. Which means mocks should be in the minority.

When you can, you should always favor either stubs or the real implementation. I haven't talked about using the real implementation (again, something the .NET community avoids like a plague), but hopefully you can see how even that isn't as crazy an idea as you've been told.

This articles had a response from Darren Cauthon:

Test Isolation Is About Avoiding Mocks

From Gary Bernhardt, in the Destroy All Software blog:

This is a large part of the claim that isolated tests drive better design. Because an isolated test must set up all collaborators as mocks, the only way to reduce the mock complexity is to reduce the depth of collaboration. If we mock three levels deep, and do nothing to reduce that mock depth, then we're spending the effort to isolate without getting the benefit. If, however, we change the design to reduce coupling, then the mock depth will also be reduced, and isolation will earn its keep.

Design isn't just reflected in isolated test setup; it's magnified. Isolated tests are a microscope for object interaction.

In addition to avoiding nested mocks, I've been using fewer over time, even when I'm writing isolated tests. The old Python system I mentioned had multiple mocks per test on average. Early DAS code written under time pressure averages around one mock per test. Later DAS code is under half a mock per test. Moving into late 2013, all of Selecta's logic is tested in isolation with no test doubles at all. (That's Functional Core, Imperative Shell again.)

In a very real sense, isolated testing done test-first exposes design mistakes before they're made. It translates coupling distributed throughout the module into mock setup centralized in the test, and it does that before the coupling is even written down.

To Kill a Mockingtest

From Ken Scambler, in the technical blog of realestate.com.au:

Please don’t use mocks or stubs in tests. While they are seemingly ubiquitous in enterprise development, they have serious drawbacks, and typically mask easily fixable deficiencies in the underlying code.

They are linked to fragile implementation details, and will constantly break under routine refactoring.

What they test is almost always beside the point of what’s actually required.

Mocks and stubs attempt to provide some level of testing in the face of entangled effects in output or input, respectively. However, in practice, almost every usage can be obviated by simply writing better code; the entanglement is the problem, and mocks only allow the developer to ignore it.

When to Mock

From Robert C. Martin, in 8th Light blog:

A mock object is a very powerful tool, providing two major benefits: isolation and introspection. But like all power tools, mocks come with a cost.

In short, however, I recommend that you mock sparingly. Find a way to test -- design a way to test -- your code so that it doesn't require a mock. Reserve mocking for architecturally significant boundaries; and then be ruthless about it.

And write your own mocks. Try to depend on mocking tools as little as possible. Or, if you decide to use a mocking tool, use it with a very light touch.

If you follow these heuristics you'll find that your test suites run faster, are less fragile, have higher coverage, and that the designs of your applications are better.

The Little Mocker

From Robert C. Martin, in 8th Light blog:

This article is written as a dialog between a teacher and a student. It explains the differences between:

  • Dummies
  • Fakes
  • Mocks
  • Spies
  • Stubs
  • Test Doubles

Mocks Aren't Stubs

From Martin Fowler, in his blog:

When you write a mockist test, you are testing the outbound calls of the SUT to ensure it talks properly to its suppliers. A classic test only cares about the final state - not how that state was derived. Mockist tests are thus more coupled to the implementation of a method. Changing the nature of calls to collaborators usually cause a mockist test to break.

This coupling leads to a couple of concerns. The most important one is the effect on Test Driven Development. With mockist testing, writing the test makes you think about the implementation of the behavior - indeed mockist testers see this as an advantage. Classicists, however, think that it's important to only think about what happens from the external interface and to leave all consideration of implementation until after you're done writing the test.

On a smaller level I noticed that mockist testers tend to ease away from methods that return values, in favor of methods that act upon a collecting object. Take the example of the behavior of gathering information from a group of objects to create a report string. A common way to do this is to have the reporting method call string returning methods on the various objects and assemble the resulting string in a temporary variable. A mockist tester would be more likely to pass a string buffer into the various objects and get them to add the various strings to the buffer - treating the string buffer as a collecting parameter.

Mockist testers do talk more about avoiding 'train wrecks' - method chains of style of getThis().getThat().getTheOther(). Avoiding method chains is also known as following the Law of Demeter. While method chains are a smell, the opposite problem of middle men objects bloated with forwarding methods is also a smell. (I've always felt I'd be more comfortable with the Law of Demeter if it were called the Suggestion of Demeter.)