2009-03-03 5 views
27

Я хотел бы создать единичный тест, используя макет веб-сервера. Есть ли веб-сервер, написанный на Java, который можно легко запустить и остановить из тестового примера JUnit?Как издеваться над веб-сервером для модульного тестирования на Java?

+2

Задача больше похожа на создание интеграционного теста, а не на единичный тест. –

ответ

11

Попробуйте Simple (Maven) его очень легко внедрить в единичный тест. Возьмите RoundTripTest и примеры, такие как PostTest, написанный с помощью Simple. Предоставляет пример внедрения сервера в тестовый пример.

Также простой намного легче и быстрее, чем Jetty, без зависимостей. Таким образом, вам не придется добавлять несколько банок в свой класс. Вы также не должны беспокоиться о WEB-INF/web.xml или других артефактах.

+2

Несмотря на то, что, возможно, это именно то, чего хочет пользователь, это не «макет» веб-сервера, который является фактическим веб-сервером, который запускается в рамках модульного теста.Например, если порт был взят, он потерпит неудачу, поэтому не настоящий макет (т. Е. Имеет внешнюю зависимость от системы). Согласно номенклатуре Мартина Фаулера [«Test Doubles»] (http://www.martinfowler.com/bliki/TestDouble.html), это «подделка». Тем не менее, это было именно то, что я искал. – ArtB

+0

Неужели этот проект не прошел? – kbolino

18

Вы пытаетесь использовать веб-сервер mock or an embedded?

Для веб-сервера издеваться, попробуйте использовать Mockito, или что-то подобное, и просто издеваются над HttpServletRequest и HttpServletResponse объекты, такие как:

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

Для веб-сервера встроенный, вы могли бы использовать Jetty, который вы можете use in tests.

6

Другой хорошей альтернативой будет MockServer; он обеспечивает свободный интерфейс, с помощью которого вы можете определить поведение издевающегося веб-сервера.

+0

Также MockServer зависит от Netty (не Jetty). –

19

Wire Mock, похоже, предлагает надежный набор заглушек и макетов для тестирования внешних веб-сервисов.

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

Он может быть интегрирован с помощью спока. Пример найден here.

+0

Это работало очень хорошо для меня. Использование wireMockConfig(). DynamicPort() делает его более предсказуемым в настройке, где другие программы могут использовать порт. Мне жаль, что это не было по умолчанию, поскольку я почти пропустил эту возможность и пропустил эту великую библиотеку. – morten

+0

Что такое testClient в коде, который вы указали? – gribo

+0

@gribo Предполагаю, что testClient - ваш фактический экземпляр под тестированием. – Stephan

5

Вы можете попробовать Jadler (http://jadler.net), который представляет собой библиотеку с плавным программным API Java для заглушки и издевки ресурсов 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"); 
+0

Я пробовал использовать Jadler, но всякий раз, когда я пытаюсь вызвать 'initJadler()', я получаю сообщение об ошибке https://github.com/jadler-mocking/jadler/issues/107. Любые мысли, что может быть неправильным? – tuk

+0

Не могли бы вы вставить результат зависимости mvn: tree здесь? Это может быть столкновение библиотек. –

+1

Пожалуйста, прочтите мой ответ в github.com/jadler-mocking/jadler/issues/107, проблема вызвана столкновением версий Jetty (8 против 9). Вы можете либо удалить зависимость Jetty9 (если это не требуется для тестового запуска), либо запустить Jadler без зависимости Jetty (https://github.com/jadler-mocking/jadler/wiki/Using-the-Alternative-Stub-Server -Implementation) –

4

Вы можете написать макет с HttpServer классе JDK, как хорошо (не требуется никаких внешних зависимостей). См. 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); 
} 
+0

Есть ли способ утверждать, получил ли запрос 'HttpServer' запрос? –

1

Если вы используете апачский HttpClient, это будет хорошей альтернативой. HttpClientMock

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

ПОЛНОЕ ОПИСАНИЕ: Я являюсь автором библиотеки.