The classical school, also called the Detroit or classicist approach, isolates unit tests from one another rather than isolating the system under test from every collaborator. A test verifies one unit of behavior, runs quickly, and remains independent of other tests. section 2.1 section 2.4
The approach makes three related choices:
- Treats a unit as a meaningful behavior, which may span a class or several classes, rather than automatically treating one class as the unit. section 2.2 section 2.3
- Keeps private collaborators real and replaces shared dependencies—those capable of making tests affect one another—with test doubles. section 2.2 section 2.5
- Prefers state-based testing and output-based testing over communication-based testing, because observable results usually resist refactoring better than interaction checks. section 6.6 section 6.6
Testing a purchase
A classical test creates a real Store, adds ten Shampoo products, and asks a real Customer to purchase five. It asserts success and the store's remaining inventory. A second test attempts to purchase fifteen and asserts failure while inventory remains ten. The tests use real in-memory collaborators but construct fresh state for each test, avoiding shared interference. section 2.4
Compared with the London school, the classical approach generally produces fewer mock interactions and less coupling to implementation details. It can include larger object graphs and may require state-based assertions, but inability to test a behavior without extensive doubles can indicate a design problem rather than justify hiding it with mocks. section 2.3 section 2.5
