P319 · Tool use

Dependency-calibrated verification adapters

Choose verification substitutes according to the dependency controlled by the module.

Editorially reviewed

These examples and illustrative results are independently authored teaching materials, not measured model results.

Use case

An order module computes totals, writes a database and calls a third-party payment service. Testing that a failed payment leaves an order pending requires more than mocking every internal function and asserting calls. First establish dependency ownership and available substitutes.

Mechanism

Classify dependencies: test in-process computation directly through the module interface; use a compatible local storage stand-in while keeping real read/write logic; put owned remote services behind a port with production transport and test adapters; inject a controlled mock adapter for external payments. Assert state through order creation/query interfaces rather than exposing internal functions. Record semantic differences and schedule appropriate contract checks.

Bad example

To test a failed order payment, mock computation, persistence, status updates and payment functions. Assert only how many times each was called.

Good example

Create an order totaling 100 through the module interface. Use a local database stand-in and a failing payment adapter, then query the order. Assert pending payment and amount 100 without depending on internal call order. State that this test does not verify the real payment network or production database differences.

Why the change matters

Substitutes should follow dependency boundaries rather than every implementation detail. Keeping module logic and feasible storage behavior lets observable tests survive internal refactoring.

Observable expectation

Teaching matrix: a successful payment adapter yields paid; explicit rejection yields pending; timeout follows the product contract as uncertain or pending rather than assuming no charge. Check queryable database results. These assertions should survive changes to internal function decomposition.

Limits

Stand-ins cannot establish production transactions, locking, network retries or third-party contract compatibility. Add a port when production and test adapters are actually justified. Delete old tests only after assessing their behavioral coverage, not mechanically because a source recommends replacement.

Sources and evidence

Read the editorial criteria