2009-03-03 7 views
27

Ich möchte einen Komponententest unter Verwendung eines Mock-Webservers erstellen. Gibt es einen in Java geschriebenen Webserver, der einfach von einem JUnit-Testfall gestartet und gestoppt werden kann?Wie spottet man einen Webserver für Komponententests in Java?

+2

Aufgabe sieht eher so aus, als würde ein Integrationstest erstellt, nicht ein Komponententest. –

Antwort

11

Versuchen Sie Simple (Maven) es ist sehr einfach in einen Komponententest einzubetten. Nehmen Sie den RoundTripTest und Beispiele wie die PostTest geschrieben mit Simple. Bietet ein Beispiel dafür, wie Sie den Server in Ihren Testfall einbetten können.

Auch einfach ist viel leichter und schneller als Jetty, ohne Abhängigkeiten. Sie müssen also nicht mehrere Gläser zu Ihrem Klassenpfad hinzufügen. Sie werden sich auch nicht mit WEB-INF/web.xml oder anderen Artefakten befassen müssen.

+2

Obwohl es wahrscheinlich ist, was der Benutzer wollte, ist dies kein "Mock" -Webserver, sondern ein tatsächlicher Webserver, der innerhalb des Komponententests gestartet wird.Zum Beispiel, wenn der Port genommen wurde, würde es fehlschlagen, also kein echter Schein (dh hat eine externe Abhängigkeit vom System). Laut Martin Fowlers Nomenklatur fore ["Test Doubles"] (http://www.martinfowler.com/bliki/TestDouble.html) ist dies ein "Fake". Das heißt, es war genau das, wonach ich suchte. – ArtB

+0

Ist dieses Projekt nicht mehr aktiv? – kbolino

18

Versuchen Sie einen mock or an embedded Webserver zu verwenden?

Für einen Mock Web-Server, versuchen Mockito, oder etwas ähnliches, und verspotten nur die HttpServletRequest und HttpServletResponse Objekte wie:

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

Für einen Web-Server eingebettet ist, könnten Sie Jetty verwenden, was Sie können use in tests.

6

Eine weitere gute Alternative MockServer wäre; Es bietet eine fließende Oberfläche, mit der Sie das Verhalten des verspotteten Web-Servers definieren können.

+0

Auch der MockServer ist abhängig von Netty (nicht Jetty). –

19

Wire Mock scheint eine solide Reihe von Stubs und Mocks zum Testen von externen Web-Services bieten.

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

Es kann mit Spock auch integrieren. Beispiel gefunden here.

+0

Das hat sehr gut für mich funktioniert. Verwenden von wireMockConfig(). DynamicPort() macht es vorhersehbarer in einer Einstellung, in der andere Programme den Port verwenden können. Ich wünschte, es wäre der Standard, da ich diese Möglichkeit fast verpasste und diese großartige Bibliothek übersprang. – morten

+0

Was ist testClient in dem von Ihnen bereitgestellten Code? – gribo

+0

@gribo Ich nehme an, testClient ist Ihre tatsächliche Instanz im Test. – Stephan

5

Sie können versuchen Jadler (http://jadler.net), die eine Bibliothek mit einer fließenden programmatischen Java-API zum Stubeln und Mock-HTTP-Ressourcen in Ihren Tests ist. Beispiel:

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

Ich versuchte mit Jadler, aber wann immer ich versuche, 'initJadler() 'aufzurufen, bekomme ich den Fehler wie erwähnt https://github.com/jadler-mocking/jadler/issues/107. Irgendwelche Gedanken, was könnte schief gehen? – tuk

+0

Könnten Sie bitte ein Ergebnis von mvn-Abhängigkeit einfügen: Baum hier? Es kann ein Zusammenstoß von Bibliotheken sein. –

+1

Bitte lesen Sie meine Antwort in github.com/jadler-mocking/jadler/issues/107, das Problem wird durch Zusammenstoß von Jetty-Versionen (8 vs 9) verursacht. Sie können entweder die Jetty9-Abhängigkeit entfernen (wenn sie für den Testlauf nicht benötigt wird) oder Jadler ohne Jetty-Abhängigkeit ausführen (https://github.com/jadler-mocking/jadler/wiki/Using-the-Alternative-Stub-Server -Implementation) –

4

Sie ein Modell mit der auch HttpServer Klasse JDK schreiben können (keine externen Abhängigkeiten erforderlich). Siehe this blog post Detaillierung wie.

Zusammengefasst:

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

Gibt es eine Möglichkeit zu behaupten, wenn der 'HttpServer' eine Anfrage erhalten hat? –

1

Wenn Sie Apache Httpclient verwenden, Das wird eine gute Alternative sein. HttpClientMock

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

vollständige Offenlegung: Ich bin der Autor der Bibliothek.

Verwandte Themen