How to mock a web server for unit testing in Java?

JavaJunit

Java Problem Overview


I would like to create a unit test using a mock web server. Is there a web server written in Java which can be easily started and stopped from a JUnit test case?

Java Solutions


Solution 1 - Java

Wire Mock seems to offer a solid set of stubs and mocks for testing external web services.

@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);


@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));
}

It can integrate with spock as well. Example found here.

Solution 2 - Java

Are you trying to use a mock or an embedded web server?

For a mock web server, try using Mockito, or something similar, and just mock the HttpServletRequest and HttpServletResponse objects like:

MyServlet servlet = new MyServlet();
HttpServletRequest mockRequest = mock(HttpServletRequest.class);
HttpServletResponse mockResponse = mock(HttpServletResponse.class);

StringWriter out = new StringWriter();
PrintWriter printOut = new PrintWriter(out);
when(mockResponse.getWriter()).thenReturn(printOut);

servlet.doGet(mockRequest, mockResponse);

verify(mockResponse).setStatus(200);
assertEquals("my content", out.toString());

For an embedded web server, you could use Jetty, which you can use in tests.

Solution 3 - Java

You can write a mock with the JDK's com.sun.net.httpserver.HttpServer class as well (no external dependencies required). See this blog post detailing how.

In summary:

HttpServer httpServer = HttpServer.create(new InetSocketAddress(8000), 0); // or use InetSocketAddress(0) for ephemeral port
httpServer.createContext("/api/endpoint", new HttpHandler() {
   public void handle(HttpExchange exchange) throws IOException {
      byte[] response = "{\"success\": true}".getBytes();
      exchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.length);
      exchange.getResponseBody().write(response);
      exchange.close();
   }
});
httpServer.start();

try {
// Do your work...
} finally {
   httpServer.stop(0); // or put this in an @After method or the like
}

Solution 4 - Java

Try Simple(Maven) its very easy to embed in a unit test. Take the RoundTripTest and examples such as the PostTest written with Simple. Provides an example of how to embed the server into your test case.

Also Simple is much lighter and faster than Jetty, with no dependencies. So you won't have to add several jar files onto your classpath. Nor will you have to be concerned with WEB-INF/web.xml or any other artifacts.

Solution 5 - Java

Another good alternative would be MockServer; it provides a fluent interface with which you can define the behaviour of the mocked web server.

Solution 6 - Java

You can try Jadler which is a library with a fluent programmatic Java API to stub and mock http resources in your tests. Example:

onRequest()
    .havingMethodEqualTo("GET")
    .havingPathEqualTo("/accounts/1")
    .havingBody(isEmptyOrNullString())
    .havingHeaderEqualTo("Accept", "application/json")
.respond()
    .withDelay(2, SECONDS)
    .withStatus(200)
    .withBody("{\\"account\\":{\\"id\\" : 1}}")
    .withEncoding(Charset.forName("UTF-8"))
    .withContentType("application/json; charset=UTF-8");

Solution 7 - Java

If you are using apache HttpClient, This will be a good alternative. HttpClientMock

HttpClientMock httpClientMock = new httpClientMock() 
HttpClientMock("http://example.com:8080"); 
httpClientMock.onGet("/login?user=john").doReturnJSON("{permission:1}");

Basically, you then make requests on your mock object and then can do some verifies on it httpClientMock.verify().get("http://localhost/login").withParameter("user","john").called()

Solution 8 - Java

Try using the Jetty web server.

Solution 9 - Java

I recommend Javalin. It's an excellent tool for mocking the real service as it allows for state assertions in your tests (server side assertions).

Wiremock can be used as well. But it leads to hard to maintain behavioral tests (verify that client calls are as expected).

Solution 10 - Java

In the interest of completeness there is also wrapping jetty with camel to make it slightly more user friendly.

make your test class extend CamelTestSupport then define a route ex:

  @Override
  protected RouteBuilder createRouteBuilder() {
    return new RouteBuilder() {
      @Override
      public void configure() {
        from("jetty:http://localhost:" + portToUse).process(
                new Processor() {
                  @Override
                  public void process(Exchange exchange) throws Exception {
                    // Get the request information.
                    requestReceivedByServer = (String) exchange.getIn().getHeader(Exchange.HTTP_PATH);

                    // For testing empty response
                    exchange.getOut().setBody("your response");
                    ....

example maven dependencies to get it:

<dependency> <!-- used at runtime, by camel in the tests -->
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-jetty</artifactId>
  <version>2.12.1</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-core</artifactId>
  <version>2.12.1</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-test</artifactId>
  <version>2.12.1</version>
  <scope>test</scope>
</dependency>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionjon077View Question on Stackoverflow
Solution 1 - JavakeaplogikView Answer on Stackoverflow
Solution 2 - JavaGene GotimerView Answer on Stackoverflow
Solution 3 - JavaJonathan SchneiderView Answer on Stackoverflow
Solution 4 - Javang.View Answer on Stackoverflow
Solution 5 - JavaHaroldo_OKView Answer on Stackoverflow
Solution 6 - JavaJan DudekView Answer on Stackoverflow
Solution 7 - Javas-han.leeView Answer on Stackoverflow
Solution 8 - JavaflybywireView Answer on Stackoverflow
Solution 9 - JavaFrank NeblungView Answer on Stackoverflow
Solution 10 - JavarogerdpackView Answer on Stackoverflow