Clean • Professional
When a Spring Boot application depends on external systems such as payment gateways, SMS/email services, OAuth providers, or third-party REST APIs, testing can become:
Mock External APIs solve this problem by allowing you to test your application without calling real external services.
A Mock External API simulates a third-party or external service during testing.
A mock API:
👉 Your application believes it is calling a real API, but a mock server handles the request.
WireMock is a popular and widely used tool for mocking HTTP/REST APIs.
It acts as a fake external server that returns predefined responses based on your configuration.
With WireMock, you can:
👉 WireMock is the most common choice in Spring Boot integration testing.
External APIs can be:
Use WireMock when:
In Spring Boot testing, mocking is used to simulate dependencies so your application can be tested in isolation, safely, and reliably. Both external systems and internal components can be mocked depending on the test scenario.
| External System / Use Case | Examples / Purpose |
|---|---|
| Payment Gateways | Razorpay, Stripe, PayPal – simulate payments, errors, and timeouts without real transactions |
| Notification Services | Email, SMS, Push Notifications – test sending functionality without real messages |
| Third-Party REST APIs | Weather API, Maps API, Currency API – simulate responses for offline or repeatable tests |
| Authentication Providers | OAuth2, SSO, Auth0 – test login flows without real authentication servers |
| Cloud Services | AWS S3, Firebase, Twilio – simulate storage, messaging, and notification services |
| Microservice APIs | Other internal services via HTTP – isolate service communication and validate integration |
👉 Use WireMock for external HTTP services, MockWebServer for lightweight HTTP mocking, and Contract stubs for producer-consumer contract verification.
| Tool | Purpose |
|---|---|
| WireMock | Mock HTTP/REST APIs (most widely used and feature-rich) |
| MockWebServer | Lightweight HTTP server for simple API mocking |
| Mockito | Mock internal Java objects and service-layer dependencies |
| Testcontainers | Run real external services (DBs, brokers, APIs) in Docker containers |
| Spring Cloud Contract Stub Runner | Use producer-generated stubs for contract-based testing |
👉 WireMock is the preferred choice for mocking external HTTP services because it supports request matching, response stubbing, delays, fault injection, and verification—making it ideal for integration and microservice testing.
Suppose your Spring Boot service calls an external API:
GET <https://external-api.com/users/1>
Expected Response:
{
"id":1,
"name":"Alice"
}
Instead of calling the real API, we mock this response using WireMock so that:
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<version>2.35.0</version>
<scope>test</scope>
</dependency>
Start WireMock on a Random Port:
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import org.springframework.boot.test.context.SpringBootTest;
@WireMockTest
@SpringBootTest
class UserServiceTest {
// WireMock starts automatically on a random port
}
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Test
void shouldFetchUserFromMockApi() {
stubFor(get(urlEqualTo("/users/1"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("""
{
"id": 1,
"name": "Alice"
}
""")));
User user = userService.getUserById(1);
assertEquals("Alice", user.getName());
}
application-test.yml
external:
api:
base-url: <http://localhost>:${wiremock.server.port}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class UserService {
@Value("${external.api.base-url}")
private String baseUrl;
private final RestTemplate restTemplate = new RestTemplate();
public User getUserById(int id) {
return restTemplate.getForObject(
baseUrl + "/users/" + id,
User.class
);
}
}
WireMock allows you to simulate failures and delays from external APIs so you can test how your application handles errors.
stubFor(get(urlEqualTo("/users/1"))
.willReturn(aResponse()
.withStatus(500)
.withHeader("Content-Type", "application/json")
.withBody("{\\"error\\":\\"Internal Server Error\\"}")));
stubFor(get(urlEqualTo("/users/1"))
.willReturn(aResponse()
.withFixedDelay(3000) // delay in milliseconds
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\\"id\\":1,\\"name\\":\\"Alice\\"}")));
You can also simulate:
WireMock can verify whether your application actually called the external API as expected:
import static com.github.tomakehurst.wiremock.client.WireMock.*;
verify(getRequestedFor(urlEqualTo("/users/1")));
@SpringBootTestWhen you want to run full integration tests with your Spring Boot context while still mocking external APIs, use @WireMockTest alongside @SpringBootTest.
@SpringBootTest
@WireMockTest
class PaymentServiceIT {
@Autowired
private PaymentService paymentService;
@Test
void shouldProcessPaymentUsingMockApi() {
// Stub external payment API
stubFor(post(urlEqualTo("/payments"))
.willReturn(aResponse()
.withStatus(201)
.withHeader("Content-Type", "application/json")
.withBody("{\\"transactionId\\":\\"tx12345\\",\\"status\\":\\"SUCCESS\\"}")));
PaymentResult result = paymentService.processPayment(new PaymentRequest(100.0, "USD"));
assertEquals("SUCCESS", result.getStatus());
assertNotNull(result.getTransactionId());
// Verify that the external API was called
verify(postRequestedFor(urlEqualTo("/payments")));
}
}
| Feature | WireMock | Mockito |
|---|---|---|
| Purpose | Mock external HTTP/REST APIs | Mock internal Java objects / methods |
| Use Case | Integration testing with real HTTP calls | Unit testing of service-layer logic |
| External Services | Yes – simulates real HTTP APIs | No – only mocks internal Java objects |
| HTTP Calls | Yes – can simulate GET/POST/PUT/DELETE calls | No – does not handle HTTP requests |
| Speed | Fast, but requires HTTP server startup | Very fast, in-memory mocks only |
| Scope | API / microservice interaction testing | Internal logic / unit testing only |
| Error Simulation | Can simulate 500 errors, timeouts, invalid responses | Only exceptions in Java methods |
| Test Reliability | Ensures correct integration with external APIs | Ensures internal behavior works as expected |
| Combination | Often used with @SpringBootTest or @WebMvcTest | Often used with @Mock or @InjectMocks |
👉 Mockito: Use for internal logic/unit tests where no real HTTP calls are involved.
👉 WireMock: Use for external API mocking, testing integration, error scenarios, and API contracts.
| Test Type | Uses Mock APIs? | Explanation |
|---|---|---|
| Unit Tests | Mockito | Mock internal service methods or objects. External APIs are not called. Very fast and isolated. |
| Integration Tests | WireMock | Mock real HTTP calls to external services. Tests service-to-service interactions reliably without hitting real APIs. |
| Contract Tests | Stubs | Use producer stubs (Spring Cloud Contract) or Pact contracts to simulate external API behavior for consumer-driven testing. |
| End-to-End Tests | Usually real APIs | Full system tests with all components. Mocks are usually avoided to test real-world behavior. |
Mocking External APIs using WireMock is a best practice in Spring Boot testing.
It ensures your tests are:
By using WireMock, you can confidently test Spring Boot applications without relying on real external systems, making your software reliable, maintainable, and production-ready.