Clean • Professional
In microservices, services communicate via APIs, and integration failures often happen due to mismatched expectations. Contract testing ensures that both consumer and provider agree on API behavior without requiring full integration setups. Pact is a leading tool for this.
Pact is a consumer-driven contract testing tool:
Benefits:
| Concept | Description |
|---|---|
| Consumer | The service calling an API (e.g., frontend or payment service) |
| Provider | The service exposing an API (e.g., order service) |
| Pact File | JSON file capturing consumer expectations |
| Pact Broker | Central repository to share and manage contracts |
| Interaction | A single request-response expectation between consumer and provider |
Consumer Service → Pact Contract → Provider Service Verification
Pact helps microservices ensure API contracts are honored between consumers and providers, avoiding integration failures.
Include Pact consumer and provider JUnit 5 libraries to write and verify contracts in Spring Boot.
<dependency>
<groupId>au.com.dius.pact.consumer</groupId>
<artifactId>junit5</artifactId>
<version>4.6.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>au.com.dius.pact.provider</groupId>
<artifactId>junit5</artifactId>
<version>4.6.8</version>
<scope>test</scope>
</dependency>
Consumers define their expectations for provider APIs using Pact contracts and test them locally.
@ExtendWith(PactConsumerTestExt.class)
@PactTestFor(providerName = "OrderService")
class PaymentConsumerPactTest {
@Pact(consumer = "PaymentService")
public RequestResponsePact createPact(PactDslWithProvider builder) {
return builder
.given("Order 123 exists")
.uponReceiving("Request order details")
.path("/orders/123")
.method("GET")
.willRespondWith()
.status(200)
.body("{\\"orderId\\":123,\\"status\\":\\"PAID\\"}")
.toPact();
}
@Test
void testOrderDetails(MockServer mockServer) {
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(mockServer.getUrl() + "/orders/123", String.class);
assertTrue(response.contains("\\"status\\":\\"PAID\\""));
}
}
@Pact → defines expected request and response.MockServer → simulates provider behavior for testing.Contract Verification is the process where the provider validates its API against consumer expectations.
Example: REST API Verification
@Provider("OrderService")
@PactBroker(host = "localhost", port = "9292") // optional
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class OrderProviderContractVerificationTest {
@TestTemplate
@ExtendWith(PactVerificationInvocationContextProvider.class)
void verifyContract(PactVerificationContext context) {
context.verifyInteraction(); // Verifies provider honors consumer contract
}
@BeforeEach
void before(PactVerificationContext context) {
context.setTarget(new HttpTestTarget("localhost", 8080));
}
}
Example: Message/Event Contract Verification
@Provider("InventoryService")
@PactBroker(host = "localhost", port = "9292")
@SpringBootTest
class InventoryProviderMessageVerification {
@TestTemplate
@ExtendWith(PactVerificationInvocationContextProvider.class)
void verifyMessageContract(PactVerificationContext context) {
context.verifyInteraction(); // Verifies message contract
}
}
Pact Broker centralizes and manages API contracts, making it easy for teams to share, version, and verify contracts across services.
Scenario: PaymentService → OrderService
/orders/{id} responseFlow:
Consumer → Pact Contract → Pact Broker → Provider Verification → Deployment
Benefits:
Pact-based contract testing ensures that microservices evolve independently without breaking consumers. It complements unit and integration testing, improves reliability, and integrates seamlessly into CI/CD pipelines, making it essential for modern microservice ecosystems.