Q24 of 40 · REST Assured

How do you mock external APIs that your service calls during a REST Assured test?

REST AssuredMidrest-assuredwiremockmockingintegration-testingapi-testing

Short answer

Short answer: Start a WireMock (or MockServer) instance before the suite and configure the service under test to call the mock's URL instead of the real external API. REST Assured tests the real service; WireMock stubs the external dependency. This lets you test error paths the real service would never return on demand.

Detail

REST Assured tests the API endpoint of your service. If that service calls a third-party API (payment gateway, email service, geocoder), you need to control what that third-party returns for deterministic tests.

WireMock approach (most common):

  1. Start WireMock on a known port before the suite
  2. Override the external service URL in your app config to point to WireMock
  3. Define stubs — what WireMock returns for given requests
  4. REST Assured tests your service as normal; WireMock intercepts the outbound call
@BeforeAll
static void startMock() {
    wireMockServer = new WireMockServer(options().port(9999));
    wireMockServer.start();
    stubFor(post(urlEqualTo("/payments"))
        .willReturn(aResponse().withStatus(200)
            .withBody("{\"status\":\"APPROVED\"}")));
}

Use cases enabled by mocking:

  • Test your service's behaviour when the payment gateway returns 503
  • Test timeout handling when the external call takes > 5 seconds
  • Test your service's response when the external API returns unexpected data
  • Verify your service sends the correct request to the external API (WireMock verify)

// EXAMPLE

PaymentIntegrationTest.java

@WireMockTest(httpPort = 9999)
class PaymentIntegrationTest extends BaseApiTest {

    @Test
    void checkout_whenPaymentApproved_returns200() {
        stubFor(post(urlEqualTo("/payment-gateway/charge"))
            .willReturn(aResponse()
                .withStatus(200)
                .withHeader("Content-Type", "application/json")
                .withBody("{\"transactionId\":\"txn-123\",\"status\":\"APPROVED\"}")));

        given(reqSpec)
            .body(Map.of("orderId", "ord-99", "amount", 49.99))
        .when()
            .post("/checkout")
        .then()
            .statusCode(200)
            .body("transactionId", equalTo("txn-123"))
            .body("status", equalTo("APPROVED"));
    }

    @Test
    void checkout_whenPaymentDeclined_returns402() {
        stubFor(post(urlEqualTo("/payment-gateway/charge"))
            .willReturn(aResponse().withStatus(402)
                .withBody("{\"status\":\"DECLINED\"}")));

        given(reqSpec)
            .body(Map.of("orderId", "ord-99", "amount", 49.99))
        .when()
            .post("/checkout")
        .then()
            .statusCode(402)
            .body("status", equalTo("DECLINED"));
    }
}

// WHAT INTERVIEWERS LOOK FOR

Knowing WireMock's role (stub the external dependency, not the service under test), how to wire the test app to call the mock URL, and the key value: testing error paths that real services won't produce on demand.

// COMMON PITFALL

Mocking the service under test itself rather than its dependencies. REST Assured should call the real running service — only external dependencies get mocked.