如何在Java中模拟Web服务器进行单元测试?

jon*_*077 40 java junit

我想使用模拟Web服务器创建一个单元测试.是否有一个用Java编写的Web服务器,可以从JUnit测试用例轻松启动和停止?

kea*_*gik 31

Wire Mock似乎提供了一组可靠的存根和模拟来测试外部Web服务.

@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));
}
Run Code Online (Sandbox Code Playgroud)

它也可以与spock集成.例如找到这里.

  • 这对我来说非常有效。使用wireMockConfig()。dynamicPort()使其在其他程序可能使用该端口的设置中更具可预测性。我希望它是默认设置,因为我几乎错过了这种可能性,并跳过了这个很棒的库。 (3认同)

Cov*_*ene 20

您是否尝试使用模拟嵌入式 Web服务器?

对于模拟 Web服务器,尝试使用Mockito或类似的东西,只需模拟HttpServletRequestHttpServletResponse对象,如:

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());
Run Code Online (Sandbox Code Playgroud)

对于嵌入式 Web服务器,您可以使用Jetty,您可以在测试中使用它.


ng.*_*ng. 13

尝试使用Simple(Maven)非常容易嵌入单元测试中.参加RoundTripTest和使用Simple编写的PostTest等示例.提供如何将服务器嵌入测试用例的示例.

Simple也比Jetty更轻,更快,没有依赖性.因此,您不必在类路径上添加几个jar.你也不必担心WEB-INF/web.xml或任何其他文物.

  • 虽然它可能是用户想要的,但这不是"模拟"Web服务器,它是在单元测试中启动的实际Web服务器.例如,如果端口被占用它将失败,因此不是真正的模拟(即确实具有来自系统的外部依赖性).根据Martin Fowler的命名["Test Doubles"](http://www.martinfowler.com/bliki/TestDouble.html),这是一个"假".也就是说,它正是我正在寻找的**. (4认同)

jks*_*der 12

您也可以使用JDK的com.sun.net.httpserver.HttpServer类编写一个模拟(不需要外部依赖项).请参阅此博客文章,详细说明如何.

综上所述:

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
}
Run Code Online (Sandbox Code Playgroud)

  • 不应使用com.sun。*类。 (2认同)
  • @TilmanHausherr com.sun.* 没问题。不应使用“sun.*”或“jdk.internal.*”。 (2认同)

Har*_*_OK 8

另一个好的选择是MockServer ; 它提供了一个流畅的界面,您可以使用该界面定义模拟的Web服务器的行为.


Jan*_*dek 6

您可以尝试Jadler,它是一个具有流畅的编程Java API的库,可以在测试中存根和模拟http资源.例:

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");
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您使用的是apache HttpClient,这将是一个不错的选择. HttpClientMock

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