A junit 5 extension for MockWebServer providing some convenience, compared to the original.
<dependency>
<groupId>de.cuioss.test</groupId>
<artifactId>cui-test-mockwebserver-junit5</artifactId>
<!-- Use the latest release; see the Maven Central badge above -->
<version>x.y.z</version>
</dependency>The MockWebServer extension provides a simple way to test HTTP/HTTPS interactions in your application. It allows you to configure mock responses for specific endpoints and verify that your code correctly handles these responses.
Here’s a basic example showing how to use the MockWebServer extension with both @MockResponseConfig and @ModuleDispatcher annotations:
@EnableMockWebServer(useHttps = true)
class MockWebServerTest {
@Test
@DisplayName("Should handle GET request with @MockResponseConfig")
@MockResponseConfig(
path = "/api/users",
method = HttpMethodMapper.GET,
jsonContentKeyValue = "users=[]",
status = 200
)
void shouldHandleGetRequest(URIBuilder uriBuilder, SSLContext sslContext) throws IOException {
// Create HttpClient with the injected SSL context
HttpClient client = HttpClient.newBuilder()
.sslContext(sslContext)
.build();
// Create request to the configured endpoint
HttpRequest request = HttpRequest.newBuilder()
.uri(uriBuilder.addPathSegment("api").addPathSegment("users").build())
.GET()
.build();
// Send request
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
// Verify response
assertEquals(200, response.statusCode());
assertEquals("{\"users\":[]}", response.body());
}
@Test
@DisplayName("Should handle POST request with @ModuleDispatcher")
@ModuleDispatcher
void shouldHandlePostRequest(URIBuilder uriBuilder, SSLContext sslContext) {
// Send POST request to the endpoint configured by getModuleDispatcher()
// ...
}
// The bare @ModuleDispatcher on the test method defers to this method to obtain the dispatcher
ModuleDispatcherElement getModuleDispatcher() {
var dispatcher = new BaseAllAcceptDispatcher("/api/posts");
dispatcher.setMethodToResult(new mockwebserver3.MockResponse.Builder()
.code(201)
.addHeader("Content-Type", "application/json")
.body("{\"id\":\"123\",\"status\":\"created\"}")
.build(), HttpMethodMapper.POST);
return dispatcher;
}
}The MockWebServer extension provides several parameter resolvers that can inject useful objects into your test methods:
| Parameter Type | Description |
|---|---|
|
The actual MockWebServer instance that can be used to configure responses, check received requests, etc. |
|
A utility for building URIs that point to the MockWebServer instance. The builder is pre-configured with the server’s host, port, and scheme. |
|
When HTTPS is enabled, this provides access to the SSL context used by the server. |
Example of using multiple parameter resolvers:
@EnableMockWebServer(useHttps = true)
class ParameterResolverTest {
@Test
@DisplayName("Should inject multiple parameters")
void shouldInjectMultipleParameters(
MockWebServer server,
URIBuilder uriBuilder,
SSLContext sslContext) {
// All parameters are automatically injected
assertNotNull(server);
assertNotNull(uriBuilder);
assertNotNull(sslContext);
// URIBuilder is configured with server details
assertEquals(server.getPort(), uriBuilder.getPort());
assertEquals("https", uriBuilder.build().getScheme());
}
}When building URIs with multiple path segments,
prefer using the addPathSegments method instead of chaining multiple addPathSegment calls:
// RECOMMENDED - Use addPathSegments for multiple path segments
URI uri = uriBuilder.addPathSegments("api", "users", "123").build();
// Less efficient approach
URI uri = uriBuilder.addPathSegment("api").addPathSegment("users").addPathSegment("123").build();The @MockResponseConfig annotation allows you to define mock responses for specific paths and HTTP methods. It can be applied at the class or method level and is repeatable.
For detailed information about using @MockResponseConfig, including the new context-aware behavior, see Working with @MockResponse.
The @ModuleDispatcher annotation provides more flexibility for configuring complex request handling logic.
For detailed information about using @ModuleDispatcher and implementing the ModuleDispatcherElement interface, see Working with @ModuleDispatcher and ModuleDispatcherElement.
The @EnableMockWebServer annotation supports several configuration options:
@EnableMockWebServer(useHttps = true, manualStart = true)
class ManualStartTest {
@Test
void shouldStartServerManually(MockWebServer server, URIBuilder uriBuilder) {
// Here we need the MockWebServer parameter to control server lifecycle
// Server is not started automatically
assertFalse(server.getStarted());
// Start the server manually
server.start();
// Now the server is running
assertTrue(server.getStarted());
// The injected URIBuilder resolves the server URL lazily, so it now builds valid URIs
URI uri = uriBuilder.addPathSegment("api").build();
assertEquals(server.getPort(), uri.getPort());
// Manual closing is unnecessary: the extension closes the server in its afterEach callback.
}
}When using manualStart = true, the injected URIBuilder binds its base URL lazily:
-
The base URL is resolved from the server the first time you call
build(), not at injection time -
You can therefore use the injected
URIBuilderdirectly, as long as you start the server before building any URI -
There is no need to create a separate
URIBuilderafter starting the server
// CORRECT - start the server first, then build from the injected URIBuilder
server.start();
URI uri = uriBuilder.addPathSegment("api").build();
// INCORRECT - building before the server is started cannot resolve the base URL yet
URI uri = uriBuilder.addPathSegment("api").build(); // server not startedFor detailed information about using HTTPS with the MockWebServer extension and configuring certificates for testing, see HTTPS Support and Certificates.
For detailed information about migrating from older versions of the MockWebServer extension to the current version, see Migration Guide.