Contract Testing Basics
Contract testing checks that the contract between services (request/response format, field types) matches, so interface changes do not cause integration failures. Common tools: Pact, Spring Cloud Contract. This article explains the idea and usage with a reference table.
Overview
- Contract: Agreement between Consumer and Provider (API spec, request/response examples). Can be JSON Schema, OpenAPI, or tool-specific format.
- Consumer-driven: Consumer defines "expected request and response"; Provider verifies it satisfies that contract. Reduces Provider breaking Consumer by surprise.
- Testing: Consumer uses a mock Provider to verify request construction and response parsing; Provider uses the contract to verify its implementation. If both pass, integration is more likely to succeed.
Example
Example 1: Flow
Plain textConsumer defines contract (Pact file) → local test with mock Provider loads contract → verifies implementation satisfies it Both pass → lower integration risk after deploy
Example 2: Pact example (conceptual)
- Consumer: Expects GET /user/1 to return {id:1, name:"..."}. Generates pact file.
- Provider: Loads pact, calls /user/1, checks response matches pact.
Example 3: Contract vs integration test
| Type | Characteristics |
|---|---|
| Contract | Lightweight, no real deploy; validates format and agreement |
| Integration | Real calls; validates end-to-end; slower, env-dependent |
- Contract tests do not replace integration tests but can catch interface mismatches earlier.
Example 4: Consumer Pact (simplified)
Java// Consumer test @PactTestFor(providerName = "user-service") void testGetUser(PactVerificationContext context) { context.verifyInteraction(); }
Core Mechanism / Behavior
- Consumer test: Stub Provider; Consumer builds request and parses response; generates pact file.
- Provider test: Provider starts; pact verifier calls endpoints; compares response to pact.
- Contract as artifact: Pact file is versioned and shared; CI runs both consumer and provider tests.
Key Rules
- Consumer-driven: Consumer defines expectations; Provider fulfills them; reduces unilateral Provider changes.
- Version the contract and align with service version; update contract first, then implement.
- Run in CI; both sides run contract tests; contract changes require agreement.
What's Next
See Service Versioning, API Gateway. See Distributed Tracing for cross-service call verification.