Clean • Professional
In modern microservices architectures, services interact over APIs, message queues, and databases. Testing these interactions in isolation is insufficient. Distributed Integration Testing (DIT) ensures that multiple services work correctly together, detecting integration issues early in development or CI/CD pipelines.
Distributed Integration Testing validates end-to-end workflows across multiple microservices to ensure the system behaves correctly.
Validate that the service ecosystem behaves correctly under realistic conditions.
Why it matters:
Example:
A Payment Service calls an Order Service to retrieve order details. A distributed integration test ensures that:
Distributed integration testing comes with its own complexities:
Example: Temporary PostgreSQL with Testcontainers:
@Container
public PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
Example: Mock Order Service for Payment Service:
WireMockServer wireMockServer = new WireMockServer(8081);
wireMockServer.stubFor(get(urlEqualTo("/orders/123"))
.willReturn(aResponse()
.withHeader("Content-Type","application/json")
.withBody("{\\"orderId\\":123,\\"status\\":\\"PAID\\"}")));
Example: Test a complete checkout flow across Payment, Order, Inventory, and Notification services in a staging environment.
| Strategy | Description |
|---|---|
| API Integration Tests | Test REST/gRPC calls between services using Spring MockMvc, RestAssured, or WebTestClient |
| Message/Event Tests | Validate messaging flows with Kafka TestUtils, RabbitMQ TestContainers, or embedded brokers |
| Database Integration Tests | Validate persistence and cross-service DB interactions using Testcontainers |
| Hybrid Approach | Combine mocks, contracts, and real services for faster and reliable integration tests |
Scenario: Validating end-to-end checkout across multiple microservices.
Services Involved:
Distributed Integration Test Flow:
Outcome: The complete checkout workflow is validated without deploying to production, ensuring multi-service integration works as expected.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
public class CheckoutFlowIntegrationTest {
@Container
public static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
@Autowired
private TestRestTemplate restTemplate;
@Test
void testCheckoutFlow() {
// Step 1: Create Order
ResponseEntity<Order> orderResponse = restTemplate.postForEntity(
"/orders",
newOrderRequest("item-123", 2),
Order.class
);
assertEquals(HttpStatus.CREATED, orderResponse.getStatusCode());
// Step 2: Process Payment
ResponseEntity<Payment> paymentResponse = restTemplate.postForEntity(
"/payments",
newPaymentRequest(orderResponse.getBody().getId(), 200),
Payment.class
);
assertEquals(HttpStatus.OK, paymentResponse.getStatusCode());
assertEquals("PAID", paymentResponse.getBody().getStatus());
// Step 3: Validate Inventory Update
ResponseEntity<Inventory> inventoryResponse = restTemplate.getForEntity(
"/inventory/item-123",
Inventory.class
);
assertEquals(8, inventoryResponse.getBody().getQuantity()); // initial 10, ordered 2
// Step 4: Notification sent (mocked)
// Optionally verify via WireMock or MockServer
}
}
Distributed Integration Testing is essential for microservices reliability: