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

时间:2009-03-03 13:14:31

标签: java junit

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

11 个答案:

答案 0 :(得分:28)

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

它也可以与spock集成。找到示例here

答案 1 :(得分:20)

您是否尝试使用mock or an embedded网络服务器?

对于模拟网络服务器,请尝试使用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());

对于嵌入式网络服务器,您可以使用Jettyuse in tests

答案 2 :(得分:13)

尝试SimpleMaven),它很容易嵌入到单元测试中。参加RoundTripTest和使用Simple编写的PostTest等示例。提供如何将服务器嵌入测试用例的示例。

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

答案 3 :(得分:8)

您也可以使用JDK的HttpServer类编写模拟(不需要外部依赖项)。请参阅this blog post详细说明如何。

总结:

HttpServer httpServer = HttpServer.create(new InetSocketAddress(8000), 0);
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);
}

答案 4 :(得分:7)

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

答案 5 :(得分: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");

答案 6 :(得分:5)

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

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

答案 7 :(得分:3)

尝试使用Jetty web server

答案 8 :(得分:1)

我推荐Javalin。这是一个模拟真实服务的出色工具,因为它允许在测试中声明状态(服务器端声明)。

Wiremock也可以使用。但这导致难以维持行为测试(验证客户端调用是否符合预期)。

答案 9 :(得分:0)

答案 10 :(得分:0)

为了完整性,还用camel包裹了码头,使其更加用户友好。

使您的测试类扩展CamelTestSupport,然后定义路由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");
                    ....

获取它的示例maven依赖项:

<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>