Free tools Windows power users keep installed
One-click scans. No signup required.
The two common schools of unit testing differ mainly in what they call a “unit” and what they isolate. Classicist (or classic) tests may exercise a small group of real objects together, while mockist (or London-school) tests typically isolate one object by replacing its collaborators with test doubles. Neither style is universally best; the right choice depends on what behavior a test needs to protect.
What are the two schools of unit testing?
The approaches are commonly called classicist/classic and mockist/London, though terminology varies. Martin Fowler describes these as styles of testing rather than rigid rules. The central questions are whether a unit can include collaborating objects, and whether isolation means keeping tests independent from one another or separating the system under test from its collaborators. See Fowler’s overview of unit tests and Manning’s chapter preview on what counts as a unit test.
| Question | Classicist/classic tendency | Mockist/London tendency |
|---|---|---|
| What is the unit? | A behavior may involve a small collaboration of objects. | Often one class or object under test. |
| What is isolated? | Tests are kept independent from one another; collaborators may be real. | The system under test is isolated from its collaborators. |
| How are collaborators handled? | Real collaborators are used when practical; doubles are an option when a dependency is unsuitable. | Collaborators are commonly replaced with doubles. |
| What is usually verified? | Resulting state or externally visible behavior. | Expected interactions or communications with collaborators. |
| Typical trade-off | A test spanning too many objects can be harder to diagnose. | Interaction expectations can couple a test to implementation details. |
How classicist tests use real collaborators
A classicist test may exercise a small cluster of objects together, provided the test remains focused. Its isolation goal is primarily to prevent one test from affecting another—not necessarily to remove every collaborator from the test. That can make the test useful for checking that objects work together as well as whether the final behavior is correct.
For example, suppose an order service calculates a total using a deterministic in-memory tax table. A classic-style test can use that real table and assert the resulting total. If the real collaborator is fast, predictable, and simple to set up, using it can expose mistakes in the interaction that a substitute might conceal.
Classicist does not mean “never use doubles.” A remote service, an unreliable dependency, or an awkward-to-construct collaborator may be better replaced. Fowler also notes that classic-style tests can verify behavior in exceptional cases such as a cache, where the interaction itself matters. The distinction is a tendency, not a prohibition. Fowler’s discussion of mocks and stubs explains this nuance.
How mockist tests isolate collaborators
Mockist tests generally focus on one object and replace its collaborators with test doubles. The test can then check not only the result but whether the object sent a particular message or made an expected call. This is especially useful when the collaboration is itself the behavior being tested.
For example, an order service that must send a confirmation email after a successful purchase can be tested with a mailer double. The test can verify that the service requested the expected email without sending a real message or depending on an external mail system. That keeps the test independent of the remote service, but it does not prove that the real mailer can deliver the message.
Interaction assertions have a cost: they may encode how the code performs a task rather than only what the task accomplishes. If implementation changes while externally visible behavior remains the same, a test that expects a particular call sequence may need updating. Fowler’s article on mocks and stubs describes the state-versus-behavior verification distinction and this refactoring trade-off.
Sociable and solitary describe test shape
Fowler uses sociable for tests that exercise interactions among real objects, and solitary for tests that focus on one unit while replacing collaborators. These terms can clarify what a test actually does without implying that one shape is automatically higher quality. A test can be valuable in either style if its boundary is deliberate and its assertions match the behavior it is meant to protect. See Fowler’s explanation of sociable and solitary tests.
How to choose a boundary for a test
Start with the purpose of the test, then decide whether a real collaborator helps or gets in the way. Consider a service that calculates an order total and may send an email:
Rank #4
- Use a real collaborator when it is deterministic, quick, and easy to configure, and when the collaboration itself is useful to exercise.
- Use a test double when the dependency is remote, slow, volatile, nondeterministic, or awkward to construct.
- Verify an interaction when making the call is part of the required behavior, such as requesting that a confirmation be sent.
- Verify a result or state when the user-visible outcome is what matters, such as the order total.
- Keep the test boundary focused so a failure points to a manageable area of behavior rather than an unnecessarily broad network of objects.
One service may call for both styles: a real in-memory collaborator for the calculation and a mailer double for the external side effect. There is no need to apply one school mechanically to every dependency or every test.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Why “unit test” can be ambiguous
Developers do not use “unit” and “integration test” with one universally shared boundary. One author may call a test of a class and its real collaborators a unit test; another may reserve that label for a single isolated class. Rather than infer the test’s shape from its label, ask what is real, what is replaced, and what boundary the assertions protect. Fowler makes this terminology caveat in “On the Diverse And Fantastical Shapes of Testing.”
Recommended Free Tools
Best Value
Why neither school replaces broader testing
A test that verifies a mock interaction does not establish that the real external system works, while a test using real collaborators may still cover only a small part of the application. Both approaches need suitable tests across broader system boundaries, including acceptance-level checks of the whole system. The aim is a useful set of tests, not a low mock count or a claim that every test must be isolated in exactly the same way. Fowler discusses this broader role in “Mocks Aren’t Stubs.”
Quick Recap
Further reading
- Vladimir Khorikov, Unit Testing Principles, Practices, and Patterns, whose publisher preview includes a chapter on the classical and London schools: Manning chapter preview.
- Steve Freeman and Nat Pryce, Growing Object-Oriented Software, Guided by Tests, recommended by Fowler as a source on mockist practice; see Fowler’s further-reading discussion.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

