liveBook · Manning

Classical school

As explained in Unit Testing Principles, Practices, and Patterns

A unit-testing approach, also called the Detroit school or classical style, that isolates tests from one another while allowing the unit under test to use real collaborator objects.

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

How Unit Testing Principles, Practices, and Patterns covers it

How deep it goes
Defines isolation, unit boundaries, dependencies, and testing styles, then contrasts trade-offs without detailing implementation internals.
Examples
Uses Customer, Store, Product, inventory, real collaborators, and contrasting mock-based purchase tests.
What it assumes
Assumes object-oriented dependencies and unit-testing familiarity while defining isolation, test doubles, and dependency categories explicitly.
What you can do after
Evaluate and design tests that isolate shared state while asserting observable behavior instead of collaborator implementation details.
How it connects
Connects unit testing with the London school, test doubles, shared dependencies, integration testing, state-based testing, and test fragility.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Unit Testing Principles, Practices, and Patterns. The section links point to the parts of the book it draws on.