Testing a service you cannot run alone

Microservices · lesson 17 of 33 · 4 min read

Push each kind of bug down to the cheapest layer of test that can still catch it.

Open this lesson in the learning hub

Key points

  • Most of your tests should be plain unit tests over your own logic. No Spring context, no Docker, milliseconds each.
  • Slices cover the edges: @WebMvcTest for controllers, @DataJpaTest for repositories. Everything else is mocked.
  • Testcontainers starts a real Postgres or Kafka for the test. A mocked repository will never catch invalid SQL.
  • Stub the services you call with WireMock or MockRestServiceServer. Never let a build call a live dependency.
  • Keep end-to-end tests few and boring. They are slow, flaky, and they usually fail for a reason that is not your bug.

Example

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@Testcontainers
class OrderFlowTest {

    // A real database for the duration of the class.
    @Container
    static PostgreSQLContainer<?> db = new PostgreSQLContainer<>("postgres:16");

    // Docker picks the port, so the properties are wired in at runtime.
    @DynamicPropertySource
    static void datasource(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", db::getJdbcUrl);
        registry.add("spring.datasource.username", db::getUsername);
        registry.add("spring.datasource.password", db::getPassword);
    }

    @Autowired
    TestRestTemplate http;

    @Test
    void placesAnOrderAgainstARealSchema() {
        // inventory is a WireMock stub; only the database is real.
        ResponseEntity<OrderView> res =
                http.postForEntity("/api/orders", new NewOrder("JCH-9", 1), OrderView.class);

        assertThat(res.getStatusCode()).isEqualTo(HttpStatus.CREATED);
        assertThat(res.getBody().status()).isEqualTo("PLACED");
    }
}

Fake what you do not own, run for real what you do, and keep end-to-end tests rare.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Microservices course, and every lesson in it is listed on the Microservices contents page.