Spring Boot Integration Testing: The Modern Guide

Master Spring Boot integration testing. Learn how to test microservices, mock external APIs, and use @SpringBootTest effectively.

Integration testing is one of the most valuable layers of the testing pyramid. Unit tests verify individual components, but integration tests validate that your application behaves correctly when multiple components interact together.

What is Integration Testing in Spring Boot?

In the Spring Boot ecosystem, integration testing typically involves starting the full Spring context using @SpringBootTest and verifying real interactions between application layers.

Integration tests commonly include:

  • Controller layer (REST endpoints)
  • Service layer (business logic)
  • Repository layer (database interactions)
  • External HTTP clients (calls to other services)

The Main Challenge: External Dependencies

External services are often the most difficult part of integration testing. Allowing tests to depend on third-party APIs such as payment providers or mapping services can introduce instability, network latency, and inconsistent results.

Traditional Approaches

Developers commonly rely on two strategies:

Mocking Internal Clients

Tools such as Mockito allow mocking HTTP client classes directly. This approach is fast but bypasses real HTTP behavior, serialization, configuration, and error handling.

HTTP Simulation Using WireMock

WireMock allows developers to simulate external HTTP services by defining expected requests and responses manually. It provides strong control over API behavior and is especially useful for contract-first or TDD workflows.

// Example WireMock simulation
@WireMockTest
class MyTest 
      @Test
      void testSomething() 
        stubFor(get("/api/resource")
        .willReturn(aResponse()
        .withStatus(200)
        .withBody("{\"id\": 1, \"name\": \"Foo\"}")));

        // Execute service logic
        
        

While WireMock is extremely powerful, manually maintaining stub data can become time-consuming as APIs evolve.

Record and Replay Testing

Another integration testing approach is record and replay. Instead of manually writing stub responses, tests capture real API interactions and reuse them later.

StableMock provides this workflow for Spring Boot integration testing.

StableMock records real HTTP interactions and converts them into WireMock-compatible stubs. It automates the creation of WireMock stubs, saving developers hours of manual work.

When NOT To Use StableMock

  • Contract-First Development: If your API doesn't exist yet, you can't record it. Use WireMock directly to design the contract.
  • Non-HTTP Protocols: StableMock focuses on HTTP/REST. For Kafka/AMQP, use Testcontainers.
  • Complex Network Failure Simulation: If you need to simulate partial packet loss or extremely specific latency patterns manually, native WireMock configuration offers more granular control.

Step 1: Add the Dependency

<dependency>
    <groupId>io.github.stablemock</groupId>
    <artifactId>stablemock</artifactId>
    <scope>test</scope>
</dependency>

Step 2: Configure Your Test

StableMock integrates with Spring Boot tests using annotations and JUnit lifecycle hooks.

@SpringBootTest
@U(urls = "https://api.stripe.com", properties = "app.stripe.url")
class ApplicationTests extends BaseStableMockTest 

            @DynamicPropertySource
            static void configureProperties(DynamicPropertyRegistry registry) 
              autoRegisterProperties(registry, ApplicationTests.class);
              
              

💡 Pro Tip: For a complete working project with tests and config, check out the Spring Boot Example Repo on GitHub.

Best Practices for Spring Boot Integration Tests

  1. Use Real Databases: Many teams use Testcontainers to run production-like database environments during integration tests.
  2. Isolate External HTTP Dependencies: Use simulation tools such as WireMock or recording tools such as StableMock, depending on your testing workflow.
  3. Randomize Ports: Use webEnvironment = WebEnvironment.RANDOM_PORT to avoid conflicts in CI environments.
  4. Keep Tests Independent: Avoid sharing state between tests and clean databases between executions.

Conclusion

Reliable integration testing requires isolating infrastructure dependencies while preserving realistic system behavior.

Combining tools such as Testcontainers for infrastructure dependencies and tools like WireMock or StableMock for HTTP dependencies helps teams build stable and maintainable test suites.

Frequently Asked Questions

What is the difference between integration testing and unit testing?

Unit tests verify individual components in isolation (mocking everything), while integration tests validate that multiple components (like Controllers, Services, and DBs) work together correctly.

When should I mock external APIs in Spring Boot?

You should mock external APIs when they are slow across the network, cost money per request, or when you need to test specific failure scenarios (like 500 errors) that are hard to reproduce with real services.

Can integration tests run offline?

Yes! By using tools like StableMock or WireMock to record and replay HTTP traffic, your integration tests can run entirely offline without needing a connection to the real third-party service.

Does StableMock replace WireMock?

No, StableMock is built on top of WireMock. It simplifies the setup for Spring Boot by adding "Record & Replay" capabilities, so you don't have to manually write JSON stubs.

Where can I find a complete StableMock Spring Boot example?

You can find a fully configured project in the official example repository on GitHub.

Explore Related Topics

Stop Rewriting Mocks By Hand, Son

Record once. Test offline forever.

Join developers who've made the switch. Free forever. No credit card required.

🌾 MIT License | 🚀 Open Source | 💯 Free Forever