The Testing Anti-Patterns Drafts: Overusing Mocks

There is something problematic about Mocks. They are just too convenient. Developers are lured into employing them all over the place, often forgetting Mocks’ primary function. And that is not the convenience of satisfying the dependencies of the code under test.

Mocks’ main purpose is to test interaction between Objects. This is why Mock verification is performed upon expectations of method calls. One of the golden rules of Unit Testing is testing one thing at a time. In this context, if there is more than one Mock per test case, this rule is probably broken.

public class CustomerServiceTest extends TestCase {

  public void testShouldSaveCustomerDetailsWithRepository() {
    Customer customer = new Customer("Kirk", "Hammet");

    CustomerRepository repository =
        EasyMock.createMock(CustomerRepository.class);
    AuditLog log = EasyMock.createMock(AuditLog.class);

    repository.save(customer);
    log.logCustomerSaved(customer);

    EasyMock.replay(repository);
    EasyMock.replay(log);

    new CustomerService(repository, log).save(customer);

    EasyMock.verify(customer);
    EasyMock.verify(log);
  }

}

Looking at the name of the test, we should be able to safely assume that we expect the CustomerService to use the CustomerRepository for saving a new Customer. Going through the code of the test, it is apparent that we are testing one more scenario apart from the interaction between the CustomerService and the CustomerRepository: We expect the CustomerService to call the logCustomerSaved(customer) method on the AuditLog. In other words, we are also testing the interaction between the CustomerService and the AuditLog.

Let’s imagine that at some point the call to logCustomerSaved(customer) is removed from the actual CustomerService code. This will result to a breaking test telling us that CustomerService Should Save Customer Details With Repository is no longer happening. This is clearly not the case.

There is a sloppy way out of situations like the above and that is stubbing the code that needs to be there in order for the test to run. This can be achieved either by coding a Stub for the AuditLog or by employing the stubbing facilities offered by Mock Object Frameworks, such as EasyMock’s createNiceMock() method. This doesn’t significantly impove readability, neither does it solve the underlying problem which is the usual suspect behind dubious tests: The Application Code is probably not modeled correctly. In the CustomerService case, logging is probably not happening in the right place.

The benefits of code being responsible for performing one task are well documented and apply to both Application and Test Code. Breaking the one mock per test limit usually signifies that this rule is not sufficiently applied.

If you’d like to follow the discussion, feel free to grab The Testing Anti-Patterns Drafts feed.

2 Responses to “The Testing Anti-Patterns Drafts: Overusing Mocks”

  1. Jay Says:

    I like the article.

    I strongly dislike the line: They are just too convenient. In fact, I think mocks are verbose and painful to maintain. I’d change that line for fear of losing readers who feel like I do, since it’s not key for your pattern.

    I’d also consider putting a before and after example.

    Still, overall, quite good.

  2. Pat Maddox Says:

    I think the real problem here is not the design, but rather that the test code is poorly written. You can read my full response at my (brand new! :) blog: http://evang.eli.st/blog/2006/11/29/one-test-class-per-production-class-the-real-testing-anti-pattern