How to use WireMock for Mocking | Examples Java Code Geeks

0
3

In this article we will learn about WireMock for mocking. WireMock is a simulator for HTTP-based APIs. Some might consider it a service virtualization tool or a mock server. It enables you to stay productive when an API you depend on doesn’t exist or isn’t complete. It supports testing of edge cases and failure modes that the real API won’t reliably produce. And because it’s fast it can reduce your build time from hours down to minutes. We will use spring boot for the example.

1. Introduction

WireMock is distributed in two flavours – a standard JAR containing just WireMock, and a standalone fat JAR containing WireMock plus all its dependencies. The standalone JAR’s dependencies are shaded i.e. they are hidden in alternative packages. This allows WireMock to be used in projects with conflicting versions of its dependencies. The standalone JAR is also runnable. Currently it is recommended that you use the standalone JAR as a dependency with Spring Boot projects. This avoids a conflict over the Jetty version.

2. Setup

To add the standard WireMock JAR as a project dependency, put the following in the dependencies section of your POM:

<dependency>
  <groupId>com.github.tomakehurst</groupId>
  <artifactId>wiremock</artifactId>
  <version>2.19.0</version>
  <scope>test</scope>
</dependency>

Or to use the standalone JAR:

<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-standalone</artifactId>
<version>2.19.0</version>
</dependency>

Gradle:

testCompile "com.github.tomakehurst:wiremock:2.19.0"

Or

testCompile "com.github.tomakehurst:wiremock-standalone:2.19.0"

JUnit 4.x
To use WireMock’s fluent API add the following import:

import static com.github.tomakehurst.wiremock.client.WireMock.*;

WireMock ships with some JUnit rules to manage the server’s lifecycle and setup/tear-down tasks. To start and stop WireMock per-test case, add the following to your test class (or a superclass of it):

@Rule
public WireMockRule wireMockRule = new WireMockRule(8089); // No-args constructor defaults

For a bit more control over the settings of the WireMock server created by the rule you can pass a fluently built Options object to either (non-deprecated) rule’s constructor:

import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
...

@Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(8089).httpsPort(8443));

Random port numbers
You can have WireMock (or more accurately the JVM) pick random, free HTTP and HTTPS ports (which is a great idea if you want to run your tests concurrently):

@Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort());

Then find out which ports to use from your tests as follows:

int port = wireMockRule.port();
int httpsPort = wireMockRule.httpsPort();

Non-JUnit and general Java usage
If you’re not using JUnit or neither of the WireMock rules manage its lifecycle in a suitable way you can construct and start the server directly:

WireMockServer wireMockServer = new WireMockServer(wireMockConfig().port(8089)); //No-args constructor will start on port 8080, no HTTPS
wireMockServer.start();

// Do some stuff

WireMock.reset();

// Finish doing stuff

wireMockServer.stop();

If you’ve changed the port number and/or you’re running the server on another host, you’ll need to tell the client:

WireMock.configureFor("wiremock.host", 8089);

And if you’ve deployed it into a servlet container under a path other than root you’ll need to set that too:

WireMock.configureFor("tomcat.host", 8080, "/wiremock");

The WireMock server can be run in its own process, and configured via the Java API, JSON over HTTP or JSON files. This will start the server on port 8080. A GET request to the root admin URL e.g http://localhost:8080/__admin will return all currently registered stub mappings. This is a useful way to check whether WireMock is running on the host and port you expect.

3. The JUnit 4.x Rule

The JUnit rule provides a convenient way to include WireMock in your test cases. It handles the lifecycle for you, starting the server before each test method and stopping afterwards.

To make WireMock available to your tests on its default port (8080):

@Rule
public WireMockRule wireMockRule = new WireMockRule();

The rule’s constructor can take an Options instance to override various settings. An Options implementation can be created via the WireMockConfiguration.options() builder:

@Rule
public WireMockRule wireMockRule = new WireMockRule(options().port(8888).httpsPort(8889));

Unmatched requests
The JUnit rule will verify that all requests received during the course of a test case are served by a configured stub, rather than the default 404. If any are not a VerificationException is thrown, failing the test. This behaviour can be disabled by passing an extra constructor flag:

@Rule
public WireMockRule wireMockRule = new WireMockRule(options().port(8888), false);

Other @Rule configurations
With a bit more effort you can make the WireMock server continue to run between test cases. This is easiest in JUnit 4.10:

@ClassRule
@Rule
public static WireMockClassRule wireMockRule = new WireMockClassRule(8089);

Unfortunately JUnit 4.11 and above prohibits @Rule on static members so a slightly more verbose form is required:

@ClassRule
public static WireMockClassRule wireMockRule = new WireMockClassRule(8089);

@Rule
public WireMockClassRule instanceRule = wireMockRule;

Accessing the stubbing and verification DSL from the rule
In addition to the static methods on the WireMock class, it is also possible to configure stubs etc. via the rule object directly. There are two advantages to this – 1) it’s a bit faster as it avoids sending commands over HTTP, and 2) if you want to mock multiple services you can declare a rule per service but not have to create a client object for each e.g.

@Rule
public WireMockRule service1 = new WireMockRule(8081);

@Rule
public WireMockRule service2 = new WireMockRule(8082);

@Test
public void bothServicesDoStuff() {
service1.stubFor(get(urlEqualTo("/blah")).....);
service2.stubFor(post(urlEqualTo("/blap")).....);

...
}

4. Stubbing

A core feature of WireMock is the ability to return canned HTTP responses for requests matching criteria.

Basic stubbing
The following code will configure a response with a status of 200 to be returned when the relative URL exactly matches /some/thing (including query parameters). The body of the response will be Hello world! and a Content-Type header will be sent with a value of text-plain.

@Test
public void exactUrlOnly() {
stubFor(get(urlEqualTo("/some/thing"))
.willReturn(aResponse()
.withHeader("Content-Type", "text/plain")
.withBody("Hello world!")));

assertThat(testClient.get("/some/thing").statusCode(), is(200));
assertThat(testClient.get("/some/thing/else").statusCode(), is(404));
}

To create the stub described above via the JSON API, the following document can either be posted to http://<host>:<port>/__admin/mappings or placed in a file with a .json extension under the mappings directory:

{
  "request": {
    "method": "GET",
    "url": "/some/thing"
  },
  "response": {
    "status": 200,
    "body": "Hello world!",
    "headers": {
      "Content-Type": "text/plain"
    }
  }
}

Requests matching an exact URL plus one of the most common HTTP methods (GET, POST, PUT, DELETE) can be stubbed like this:

stubFor(get("/some/thing")
.willReturn(aResponse().withStatus(200)));

Common responses can also be abbreviated e.g.:

stubFor(delete("/fine")
.willReturn(ok()));

stubFor(get("/fine-with-body")
.willReturn(ok("body content")));

stubFor(get("/json")
.willReturn(okJson("{ "message": "Hello" }")));

stubFor(post("/redirect")
.willReturn(temporaryRedirect("/new/place")));

stubFor(post("/sorry-no")
.willReturn(unauthorized()));

stubFor(put("/status-only")
.willReturn(status(418)));

Setting the response status message
In addition to the status code, the status message can optionally also be set.

Java:

@Test
public void statusMessage() {
    stubFor(get(urlEqualTo("/some/thing"))
            .willReturn(aResponse()
                .withStatus(200)
                .withStatusMessage("Everything was just fine!")
                .withHeader("Content-Type", "text/plain")));

    assertThat(testClient.get("/some/thing").statusCode(), is(200));
    assertThat(testClient.get("/some/thing/else").statusCode(), is(404));
}</pre
JSON:
{
    "request": {
        "method": "GET",
        "url": "/some/thing"
    },
    "response": {
        "status": 200,
        "statusMessage": "Everything was just fine!"
    }
}

5. WireMock for mocking – Conclusion

In this article we learned how to use WireMock to stub a rest service. We learned how to setup the WireMock for different projects (Maven/Gradle etc).  Then we learned how we can use WireMock in JUnit to mock certain behaviour. In the end we learned about different way of stubbing an API. There are lots which you can do with WireMock but this is only a small article which concentrate of describing various ways of set-up using very basic example.

6. Download the Source Code

Download
You can download the full source code of this example here: WireMock Example

LEAVE A REPLY

Please enter your comment!
Please enter your name here