How to use WireMock for Mocking
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
You can download the full source code of this example here: WireMock Example
source code is empty project