在jetty中使用存根服务器测试应用程序



我正在为一个通过http访问web服务的应用程序编写测试。我想创建一个存根服务器,在那里我可以验证来自客户端应用程序的请求,并发送一个存根响应。我正在尝试使用jetty,但它的API文档相当缺乏。我想有一些东西,在那里我可以从套接字流获取和解析HTTP请求,发送存根响应和反省请求。下面是一个虚拟代码,我测试客户端是否发送了一个正确的头:

public class MyTestSuite {
ServerSocket serverSock;
ExecutorService executor;
@BeforeMethod
public void setupServerSocket() throws IOException {
serverSock = new ServerSocket(0);
}
@AfterMethod
public void teardownServerSocket() throws IOException {
serverSock.close();
}
@Test
public void myTest() {
Future<HttpField> result = executor.submit(() -> {
try (Socket sock = serverSock.accept()) {
// I need a way to create a request from the stream
Request req = ...;
// I need to initialize and send a response stub
Response rep = ...;
sock.getOutputStream().write(...);
// ...and return any value I want to inspect
return req.getField("Content-Type");
}
});
clientUnderTest.methodUnderTest();
var field = result.get();
assertEquals(field.getHeader(), HttpHeader.CONTENT_TYPE);
assertEquals(field.getValue(), "application/json");
}
}

jetty的HttpTesterHttpParser看起来是可行的,但是它们的文档记录很差。这是存根服务器的正确方法吗?

一种方法是使用startServer(Handler)技术。

package jetty;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.component.LifeCycle;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestingExampleStartServer
{
private static Server server;
private URI serverBaseURI;
public void startServer(Handler handler) throws Exception
{
server = new Server(0);
server.setHandler(handler);
server.start();
serverBaseURI = server.getURI().resolve("/");
}
@AfterAll
public static void stopServer()
{
LifeCycle.stop(server);
}
@Test
public void testHandler() throws Exception
{
startServer(new AbstractHandler() {
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
{
// do something custom here
response.setHeader("X-Foo", "Bar");
baseRequest.setHandled(true);
// assert here if you want
}
});
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest
.newBuilder(serverBaseURI)
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
assertEquals(200, response.statusCode());
assertEquals("Bar", response.headers().firstValue("X-Foo").orElse(null));
}
}

另一种是让HandlerCollection随意添加

package jetty;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.component.LifeCycle;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestingExampleMutableCollection
{
private static Server server;
private static URI serverBaseURI;
private static HandlerCollection handlers;
@BeforeAll
public static void startServer() throws Exception
{
server = new Server(0);
handlers = new HandlerCollection(true);
server.setHandler(handlers);
server.start();
serverBaseURI = server.getURI().resolve("/");
}
@AfterAll
public static void stopServer()
{
LifeCycle.stop(server);
}
private void setHandler(Handler ... handlerList)
{
// use .setHandlers(Handler[]) to reset the list, removing other handlers already present.
handlers.setHandlers(handlerList);
}
@Test
public void testHandler() throws Exception
{
setHandler(new AbstractHandler() {
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
{
// do something custom here
response.setHeader("X-Foo", "Bar");
baseRequest.setHandled(true);
// assert here if you want
}
});
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest
.newBuilder(serverBaseURI)
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
assertEquals(200, response.statusCode());
assertEquals("Bar", response.headers().firstValue("X-Foo").orElse(null));
}
}

但是最简单的方法是不使用@BeforeAll@AfterAll,并且每个测试使用一个唯一的服务器实例。(Jetty启动小于100ms)

package jetty;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.component.LifeCycle;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestingExampleLocalServer
{
@Test
public void testHandler() throws Exception
{
Server server = new Server(0);
server.setHandler(new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
{
// do something custom here
response.setHeader("X-Foo", "Bar");
baseRequest.setHandled(true);
// assert here if you want
}
});
server.start();
try
{
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest
.newBuilder(server.getURI().resolve("/"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
assertEquals(200, response.statusCode());
assertEquals("Bar", response.headers().firstValue("X-Foo").orElse(null));
}
finally
{
LifeCycle.stop(server);
}
}
}

最新更新