Mockist vs Classical testing strategy

Romain Brunie
3 min readJun 16, 2021

We learned in the previous article the difference between Behavior vs State verification. Depending on the testing style, we use either one or the other verification style. This article is about testing style and shows how each style impacts TDD.

Mockist TDD

The mockist strategy is also known by London School strategy, Outside-in, or white box testing. The mockist TDD style tests system interactions.

Fixture Setup

The mockist TDD style create the SUT and always use mocks for its collaborators.

Design Style

Mockist TDD promotes a style called need-driven development. We first develop from the outside of the system (UI for example). We then think about expectations and interactions between the SUT and collaborators. It makes us think ahead with the implementation of the production code through the mocks. The expectations/assumptions, about mocks created, become the starting points for our other tests. We repeat the process by testing one SUT at a time. Mocks drive the design of our system.

Test Coupling

This strategy couples tests to the production code. So, if we change an object or method signature, we will have compile errors on all of our tests using these mocks. However, it is easy to point out the problem with mockist TDD because only tests whose SUT contains the bug will fail.

Classical TDD

The classicist strategy is also known by Detroit School strategy, Inside-out, black box testing, or state based testing. The classical TDD style tests system boundaries. A classic TDDer can use any test double. It might use mock if the collaboration between the SUT and the collaborator make state verification impossible.

Fixture Setup

The classical TDD style creates the SUT, and uses real objects if possible or a double if the collaborator is (cf. Test Double):

  • slow to run, or
  • a production service that cannot be used for testing, or
  • unreliable.

It uses a factory (also called objectMother) to create them.

Design Style

This style also affects the design of our system. It can follow the same approach used with mocks, but with stubs instead. There is another approach called inside-out. We first develop the domain for the feature to work. Then, we go one layer above and create the SUT and collaborators if needed. With this strategy, we do not need to stub or mock anything. It also helps to keep domain logic from leaking into the UI.

Test Isolation

If we change an object or method signature on an object, it will not affect any test. However, if we introduce a bug in our system, many tests can fail where the buggy object is a collaborator. The use of an objectMother simplifies object creations since we can reuse objects instantiations. This is a drawback for mockist since a bug can produce a ripple effect throughout our test suite..

Conclusion

To get a good test coverage, there are many strategies. Our strategy choice depends if we prefer to focus on the result of the behavior or how it is implemented.

--

--

Romain Brunie

Passionate about Clean Code and Software Craftsmanship @AVIV