API and contract
Two typologies share this page because they share their tooling: integration and contract. The distinction between them is not the tool — it is whether the thing being verified is our side of the boundary or the agreement between two sides.
Testcontainers
Section titled “Testcontainers”Real technology, started for the test in a container, thrown away after.
The single most valuable tool in this section, because it is what makes ephemeral environments the default and removes the need for the shared integration environment. A PostgreSQL container starts in a couple of seconds; a shared PostgreSQL costs an afternoon a month in cross-contamination and drift.
Bindings for the JVM, Go, Python, Node, .NET and Rust. Modules for essentially every database, broker, cache and object store, and a generic container for anything with an image.
Use the same version as production. A test against PostgreSQL 15 while production runs 17 is testing a different query planner.
Reuse containers locally, not in CI. Reuse makes the local loop fast; in CI it reintroduces shared state, which is the thing being escaped.
One container per test class, not per test method, unless the tests mutate in ways that cannot be cleaned up. The startup cost is per container.
WireMock
Section titled “WireMock”A mock HTTP server — the real HTTP stack, real serialisation, real timeouts — rather than a mocked client. This is the difference between testing our integration and testing our belief about our integration.
Its underused half is failure simulation, which is most of what
resilience testing needs at integration level:
fixed delays, random delays, connection resets mid-response, malformed bodies,
503s, 429s with a Retry-After. Verifying that a timeout fires, that retries
back off, and that a circuit breaker opens costs almost nothing here and is
expensive to verify anywhere else.
Microcks
Section titled “Microcks”Mocking and conformance testing driven by the contract itself — OpenAPI, AsyncAPI, gRPC, GraphQL, or a Postman collection.
It is the tool that closes the loop that WireMock leaves open. A hand-written WireMock stub encodes what we believe the provider does, which may be the same misunderstanding that is in our code. A Microcks mock is generated from the contract, so the consumer cannot drift from it silently.
Two directions, and both matter:
As a mock, for consumers: a runnable version of the API from the day the contract is agreed, before the provider is built. This is what makes API-first practical rather than aspirational.
As a conformance test, for providers: replay the contract’s examples against the real implementation and assert it complies. This is the provider half of contract testing with no additional artefact to maintain — the contract is the test.
It runs as a container, so it belongs in the pipeline rather than in an environment somebody administers. Contracts come from api-hub.
Consumer-driven contracts, for the case Microcks does not cover: when the consumer’s actual usage should constrain the provider rather than the published specification.
Each consumer publishes the subset of the interaction it depends on; the provider verifies against every published expectation. The payoff is precision about what may safely change — a field no consumer reads can be removed, mechanically established rather than asked around.
The cost is real: a broker to run, a publish step in every consumer pipeline, and cooperating consumers. Worth it between teams inside one organisation, rarely worth it for a public API with unknown consumers — which is exactly where the specification-driven approach belongs instead.
Schemathesis
Section titled “Schemathesis”Property-based conformance against an OpenAPI document: it generates requests from the schema — including the boundary values and the malformed inputs nobody writes by hand — and checks that responses conform, that the server does not return 500, and that documented status codes are the ones produced.
Cheap to add, since the input already exists, and it reliably finds the unhandled-input class of defect that hand-written tests miss because the author was thinking about the happy path.
Choosing between them
Section titled “Choosing between them”| Question | Tool |
|---|---|
| Do we use this database correctly? | Testcontainers |
| Do we handle that API’s failures correctly? | WireMock |
| Does our provider comply with its published contract? | Microcks |
| Does our consumer match the contract it was written against? | Microcks mock |
| What may we safely change, given who actually calls us? | Pact |
| Does our API survive inputs nobody wrote a test for? | Schemathesis |