🎯 Use Case
We have an API that integrates with an external service. With ongoing development changes, we need to test our API as an isolated component whenever necessary.
⚔️ Challenge
Testing our API component against the actual external API isn’t always practical. There are several challenges that can arise—such as the external service being temporarily unavailable, rate limits that restrict frequent calls, or even costs associated with hitting production-like environments. Despite these limitations, we still need the flexibility to test our component reliably and independently, without relying on the external API’s availability or behaviour.
🚀 Approach
So, how can we overcome this dependency? One effective solution is to mock the external API during testing.
As an example, let’s take our petstore-api-demo app. When we invoke it, it internally makes a call to an external remote Pet Store service.

Implementation approach
To implement this setup, we can use WireMockServer, which allows us to mock external API calls without actually reaching out to the real external service. This is particularly useful for isolated and reliable testing.
We’ll use @SpringBootTest to structure our integration test, and we’ll start the WireMock server as part of the test setup. This way, the test can simulate the external API responses while keeping everything self-contained and repeatable.
✅ 1. Add WireMock Dependency
testImplementation 'org.wiremock:wiremock-standalone:3.3.1'✅ 2. Create an application-test.yaml for Testing
When running the integration tests, we plan to use a dedicated test application YAML configuration file instead of the real integration configuration. This ensures that our tests are isolated and use mock endpoints rather than actual external services.
external:
pets-tore:
url: http://localhost:9561✅ 3. Create @SpringBootTest with WireMock Server
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@DisplayName("Pet API Integration Test with WireMock")
public class PetControllerIntegrationTest {
private WireMockServer wireMockServer;
@LocalServerPort
private int port;
private final TestRestTemplate restTemplate = new TestRestTemplate();
@BeforeAll
void startWireMock() {
wireMockServer = new WireMockServer(9561); // Port must match test YAML
wireMockServer.start();
configureFor("localhost", 9561);
stubFor(get(urlEqualTo("/pet/1"))
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withBody("""
{
"id": 1,
"category": {
"id": 1,
"name": "string"
},
"name": "doggie",
"photoUrls": [
"string"
],
"tags": [
{
"id": 1,
"name": "string"
}
],
"status": "available"
}
""")
.withStatus(200)));
}
@AfterAll
void stopWireMock() {
wireMockServer.stop();
}
@Test
void testGetPetById_shouldReturnMockedPet() {
String url = "http://localhost:" + port + "/api/v1/pet/1";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).contains("doggie");
}
}- We use the @ActiveProfiles(“test”) annotation to activate the application-test.yaml configuration during testing. This ensures that the test environment uses the appropriate mock settings and avoids calling real external services.
- @BeforeAll
- Start on port 9561
- Launch WireMock
- Configure WireMock to accept requests
- Set up a stub/mock for GET /api/v1/pet/1
- When your app calls
GET http://localhost:9561/api/v1/pet/1, WireMock will return a mocked200 OKresponse with the given JSON.
- @AfterAll : Stops the WireMock server that was started in
@BeforeAll. - @Test
- Sends a real HTTP GET request to your running Spring Boot app (
/api/v1/pet/1) - Your app internally makes a mocked call to WireMock
- The test verifies:
- The response status is 200 OK
- The body contains
"doggie"(from the WireMock stub)
- Sends a real HTTP GET request to your running Spring Boot app (

