liveBook · Manning

State-based testing

As explained in Unit Testing Principles, Practices, and Patterns

A unit-testing style that verifies the state of the system under test, a collaborator, or an out-of-process dependency after an operation.

State-based testing verifies the state of the system after an operation completes. The checked state may belong to the system under test, a collaborator, or an out-of-process dependency such as a database or filesystem. section 6.1

Unlike output-based testing, which checks a return value, state-based testing checks changes produced by an operation. It is generally stronger than communication-based testing but weaker than output-based testing on resistance to refactoring and maintainability. section 6.0 section 6.2

Adding a product to an order

After calling AddProduct, the test checks that the order contains exactly one product and that it is the product supplied. The assertions verify the resulting collection rather than a return value or an interaction with a mock.

Use state-based tests with these constraints:

  • Assert observable state rather than exposing private state solely to make testing possible. section 6.6
  • Expect larger tests and moderate maintainability costs when assertions span several state properties. section 6.2
  • Reduce assertion noise with helper methods or value objects, while recognizing that these techniques mitigate rather than eliminate the cost. section 6.6
  • Prefer output-based testing when the code can be separated from side effects; retain state-based tests when that transformation is not reasonably worthwhile. section 6.4 section 6.5

Filesystem-backed audit system

A filesystem-coupled audit system can be tested by inspecting written files, but those tests are slow and difficult to maintain. Injecting a filesystem abstraction improves feedback, while refactoring AuditManager to return a FileUpdate enables concise output-based tests. This illustrates a migration path, not a requirement to eliminate every state-based test. section 6.4

How Unit Testing Principles, Practices, and Patterns covers it

How deep it goes
Defines the style, compares trade-offs, demonstrates assertions, and stops short of requiring total conversion to output-based testing.
Examples
Uses an Order collection, Article comments, and a filesystem-backed audit system to demonstrate state assertions and refactoring.
What it assumes
Assumes unit-testing concepts such as a system under test and observable behavior, while defining the three testing styles through examples.
What you can do after
Apply it by asserting observable system, collaborator, or dependency state while managing brittleness and maintenance cost.
How it connects
Connects state-based testing with output-based testing, communication-based testing, observable behavior, encapsulation, and functional architecture.

Also explained in

Compare how 2 books explain state-based testing →

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.