Adding a MockWebServer JUnit Jupiter Extension
- sleberknight
- Jul 5
- 2 min read
In the last post, I used several utilities in the kiwi-test library to clean up and remove boilerplate from tests using OkHttp's MockWebServer. But there's something else we can do to remove even more boilerplate from tests. The tests in the previous two blogs have the same code in the @BeforeEach and @AfterEach methods to:
Create a new MockWebServer instance and set an instance field
Get the base URI for the server where tests can send requests
Close the server after each test completes
This setup and teardown logic can be extracted into a JUnit Jupiter extension that will:
Before each test, create a new MockWebServer
Provide methods to get the server instance and the base URI of the server
After each test, close the server
Here is one implementation:
This implementation provides two constructors. The no-arg constructor creates a MockWebServer instance for you, while the one-arg constructor lets you create your own instance with any customization your tests need. For example, to support TLS.
It also provides the server() and uri() methods to easily get the MockWebServer instance and the base URI for use in your tests. Note these methods are generated usng Lombok, though they would be easy enough to create manually.
Using the extension in tests is straightforward. You add a MockWebServerExtension instance field and annotate it with @RegisterExtension:
For convenience, you can also declare a MockWebServer field:
Then in your test's @BeforeEach method, you initialize the server field, which can then be referenced in tests.
Alternatively, you can get the server in each test using the extension's server() method:
Since the extension takes care of closing the server, you don't need to have a custom @AfterEach method to do that.
Now, you can write a complete test that uses the extension like the following:
This test's @BeforeEach method gets the MockWebServer and the base URI directly from the MockWebServerExtension. So the only initialization logic it needs to do is to create a Jersey client and an instance of the class being tested, MathApiClient. As mentioned earlier, the test doesn't need to close the server in the @AfterEach method, so all it needs to do is close the Jersey client.
Each test then is the same as the previous post, where we used RecordedReqests and RecordedRequestAssertions from kiwi-test to keep the test code clean.
And that's all there is to it! The extension code shown above provides what you need in the majority of testing situations. But you don't need to create your own or copy this code if you don't want. kiwi-test version 3.9.0 adds its own MockWebServerExtension. It is very similar to the extension show here, but adds a few additional features such as the ability to specify a "server customizer", which is a Consumer<MockWebServer> that lets you customize a server, for example, to add TLS support and only support HTTP 1.1 and 2.0:
It also provides a uri(path) method that lets you easily get a URI relative to the base URI of the server:
Wrapping Up
Using a JUnit extension like the MockWebServerExtension shown here is one more thing you can do to eliminate boilerplate code in your tests. It can also provide the flexibility needed by different tests by allowing customization of the MockWebServer.
Comments