Contract testing checks whether independently developed components can communicate according to an agreed interface. A consumer is the component making a request or processing a message; a provider supplies the response or publishes the message. Their contract can describe HTTP methods, paths, headers, request bodies, response fields, error formats, and message schemas. The objective is to detect incompatible assumptions at the boundary rather than verify every internal business rule.
For example, an order application might call an external payment API and expect a successful authorization response containing a string authorizationId and a recognized status value. Consumer tests can run against a mock API that returns these agreed responses. They should verify that the application sends the expected request and correctly handles representative success and error responses. However, passing against a mock proves compatibility only with that mock. Provider verification must separately establish that the real implementation satisfies the same expectations.
Contracts can originate from a provider-owned specification, such as an OpenAPI document, or from executable consumer expectations. In a consumer-driven workflow, consumer tests produce an interaction contract that the provider verifies against its implementation. A specification-driven workflow can validate requests and responses against a shared interface definition. Neither approach should rely solely on manually maintained example payloads, because those examples can drift from actual behavior.
In cloud development environments, configure external dependency endpoints so applications can use isolated mock APIs instead of production systems. A mock server can run locally, in a build container, or behind a dedicated development endpoint. Amazon API Gateway REST APIs also support mock integrations for returning configured responses without calling a backend. Such mocks are useful test doubles, but they do not automatically verify compatibility with the real external provider. Keep credentials and test data separate from production, and avoid live operations that charge customers or modify real accounts.
A practical pipeline runs consumer tests against controlled mocks, publishes versioned contract artifacts, and runs provider verification when the provider is under the team's control. Fail the relevant build or deployment gate when required interactions become incompatible. For third-party APIs that cannot execute your contracts, use published specifications and sandbox checks where available, recognizing that the resulting assurance is weaker than coordinated provider verification.
Choose assertions carefully. Removing a required field, changing a numeric value to a string, or changing an expected status code can break consumers. Adding an optional response field is often compatible, but strict deserializers can still reject it. Prefer assertions about required behavior over exact equality of entire payloads when extra fields are intentionally allowed. Include agreed error responses and distinguish a valid error payload from transport failures such as timeouts.
Contract tests complement rather than replace integration and end-to-end tests. An integration test exercises components together, while a contract test specifically checks their boundary agreement; some tests serve both purposes. Contract verification does not establish production networking, IAM permissions, TLS configuration, latency, or availability. Keep a smaller set of tests against real development or sandbox dependencies to cover those risks. The main trade-off is faster, more deterministic feedback in exchange for maintaining contracts, representative fixtures, and verification workflows.