Verifying HTTP requests with Wiremock

When interacting with an external service, is very common to use mock servers to simulate its capabilities and test if what we are developing in practice works. This is an example on how we can achieve this.

In other cases, what we need is only to inspect the HTTP request sent from our services to verify whether it is correct or not. This post describes how you can achieve this using Wiremock.

Wiremock + JUnit

Wiremock is a simulator for HTTP-based APIS, most known as a mock server. When used together with JUnit, it enables us to do unit tested HTTP request verification. I’ve been using it to test this simple library APNS Messaging.

The very first step is to add JUnit and Wiremock to our project. We can do it using Maven:

<dependency>
  <groupId>com.github.tomakehurst</groupId>
  <artifactId>wiremock</artifactId>
  <version>2.26.3</version>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-api</artifactId>
  <version>5.6.1</version>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-engine</artifactId>
  <version>5.6.1</version>
</dependency>

or Gradle:

testImplementation 'com.github.tomakehurst:wiremock:2.26.3'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.1'

With that set, is time to write our JUnit test:

The unit test

With the dependencies in place, we’ll have access to the WiremockServer class that we’ll use to verify our requests. Let’s create our Wiremock server and Java 11’s HTTP client:

  static WireMockServer wireMockServer;
  static HttpClient httpClient;

  @BeforeAll
  static void prepare() throws Exception {
    wireMockServer = new WireMockServer(wireMockConfig().dynamicPort());
    httpClient = HttpClient.newBuilder()
      .version(HttpClient.Version.HTTP_2)
      .build();

    wireMockServer.start();
  }

  @AfterAll
  static void release() {
    wireMockServer.stop();
  }

Before any test is executed, we are assigning a random port available to the Wiremock server and also creating a Java 11’s HTTP client asking it to try and upgrade any request to HTTP/2. We stop the Wiremock server after the tests are executed.

When the Wiremock server starts, it will record all the requests sent, allowing us to inspect it. Let’s make the HTTP request and inspect it:

@Test
@DisplayName("Should send basic request")
void sendBasicRequest() throws IOException, InterruptedException {
  HttpRequest httpRequest = HttpRequest.newBuilder()
    .uri(URI.create("http://localhost:" + wireMockServer.port() + "/actions"))
    .header("content-type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("{\"key\":\"Value\"}"))
    .build();

    httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
    wireMockServer.verify(postRequestedFor(urlEqualTo("/actions"))
      .withHeader("content-type", equalTo("application/json"))
      .withRequestBody(matchingJsonPath("$.key", equalTo("Value"))));
  }

From the Wiremock server instance, we are now able to check headers, verify how many requests were made or inspect the content of the body. Here is the example put together:

class WiremockTest {

  static WireMockServer wireMockServer;
  static HttpClient httpClient;

  @BeforeAll
  static void prepare() throws Exception {
    wireMockServer = new WireMockServer(wireMockConfig().dynamicPort());
    httpClient = HttpClient.newBuilder()
      .version(HttpClient.Version.HTTP_2)
      .build();

    wireMockServer.start();
  }

  @AfterAll
  static void release() {
    wireMockServer.stop();
  }

  @Test
  @DisplayName("Should send basic request")
  void sendBasicRequest() throws IOException, InterruptedException {
    HttpRequest httpRequest = HttpRequest.newBuilder()
      .uri(URI.create("http://localhost:" + wireMockServer.port() + "/actions"))
      .header("content-type", "application/json")
      .POST(HttpRequest.BodyPublishers.ofString("{\"key\":\"Value\"}"))
      .build();

    httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
    wireMockServer.verify(postRequestedFor(urlEqualTo("/actions"))
      .withHeader("content-type", equalTo("application/json"))
      .withRequestBody(matchingJsonPath("$.key", equalTo("Value"))));
  }
}

Conclusion

Wiremock is simple to use and enables us to guarantee what is going into the wild. It also allows us to do stubbing, simulating services that aren’t yet available or complete.

The source code is available on GitHub.

That’s it for now! See you next time :)