Multi-domain API Mocking with WireMock#
A typical usage pattern is to run a WireMock instance per API you need to mock and configure your app to treat these instances as endpoints.
However, it's also possible to mock multiple APIs in a single instance via the use of the proxying and hostname matching features. There are two advantages of this approach - lower overhead (memory, startup/shutdown time), and no need to modify each base URL in your app's configuration. It can also avoid some of the headaches associated with binding to random ports.
The key steps to enabling this configuration are:
- Enable browser (forward) proxying via
.enableBrowserProxying(true)
in the startup options. - Configure the JVM's proxy settings to point to the WireMock instance using
JvmProxyConfigurer
.
The following sections detail how to achieve this in various deployment contexts.
Configuring for JUnit Jupiter#
The simplest way to enable this mode if you're using JUnit Jupiter it to toggle it on via the WireMockExtension
. See the
Junit Jupiter Proxy Mode for details.
Configuring for JUnit 4.x#
To use this mode with the JUnit 4.x rule we:
- Create the rule as usual with browser proxying enabled.
- Ensure our HTTP client (the one used by our app to talk to the API we're mocking) honours the system properties relating to proxy servers.
- Set the proxy properties using
JvmProxyConfigurer
before each test case and unset them afterwards. - Specify the host name we're targeting when creating stubs.
public class MultiDomainJUnit4Test {
@Rule
public WireMockRule wm = new WireMockRule(options()
.dynamicPort()
.enableBrowserProxying(true)
);
HttpClient httpClient = HttpClientBuilder.create()
.useSystemProperties() // This must be enabled for auto proxy config
.build();
@Before
public void init() {
JvmProxyConfigurer.configureFor(wm);
}
@After
public void cleanup() {
JvmProxyConfigurer.restorePrevious();
}
@Test
public void testViaProxy() throws Exception {
wm.stubFor(get("/things")
.withHost(equalTo("my.first.domain"))
.willReturn(ok("Domain 1")));
wm.stubFor(get("/things")
.withHost(equalTo("my.second.domain"))
.willReturn(ok("Domain 2")));
HttpResponse response = httpClient.execute(new HttpGet("http://my.first.domain/things"));
String responseBody = EntityUtils.toString(response.getEntity());
assertEquals("Domain 1", responseBody);
response = httpClient.execute(new HttpGet("http://my.second.domain/things"));
responseBody = EntityUtils.toString(response.getEntity());
assertEquals("Domain 2", responseBody);
}
}
Configuring for other Java#
To use this mode from Java code we:
- Create and start a
WireMockServer
instance with browser proxying enabled. - Ensure our HTTP client (the one used by our app to talk to the API we're mocking) honours the system properties relating to proxy servers
- Set the proxy properties using
JvmProxyConfigurer
before each bit of work and unset them afterwards. - Specify the host name we're targeting when creating stubs.
public void testViaProxyUsingServer() throws Exception {
WireMockServer wireMockServer = new WireMockServer(options()
.dynamicPort()
.enableBrowserProxying(true)
);
wireMockServer.start();
HttpClient httpClient = HttpClientBuilder.create()
.useSystemProperties() // This must be enabled for auto proxy config
.build();
JvmProxyConfigurer.configureFor(wireMockServer);
wireMockServer.stubFor(get("/things")
.withHost(equalTo("my.first.domain"))
.willReturn(ok("Domain 1")));
wireMockServer.stubFor(get("/things")
.withHost(equalTo("my.second.domain"))
.willReturn(ok("Domain 2")));
HttpResponse response = httpClient.execute(new HttpGet("http://my.first.domain/things"));
String responseBody = EntityUtils.toString(response.getEntity()); // Should == Domain 1
response = httpClient.execute(new HttpGet("http://my.second.domain/things"));
responseBody = EntityUtils.toString(response.getEntity()); // Should == Domain 2
wireMockServer.stop();
JvmProxyConfigurer.restorePrevious();
}