我正在编写集成JUnit测试。我的任务是测试本地服务器的响应是否正确。上述服务器将GET参数作为要分析的页面地址(例如:localhost:8000/test?url=http://www.example.com
)。
为了避免依赖于www.example.com我想开始这个特定的测试我自己的码头服务器,它始终提供相同的内容。
private static class MockPageHandler extends AbstractHandler {
public void handle(String target,Request baseRequest, HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html; charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
final String responseString = loadResource("index.html");
response.getWriter().write(responseString);
baseRequest.setHandled(true);
}
}
public void test() throws Exception {
final int PORT = 8080;
final Server server = new Server(PORT);
server.setHandler(new MockPageHandler());
server.start();
final ContentResponse response =
client.newRequest("http://localhost:8000/test?url=http://localhost:8080").send();
/* some assertions. */
server.stop();
server.join();
}
每次执行此测试时,都不会调用handle
中的MockPageHandler
方法。
你有什么建议为什么不起作用?
P.S。当我删除server.stop()
并在浏览器中输入http://localhost:8080
时,会显示正确的页面。
答案 0 :(得分:5)
快速回答:
删除server.join()
行。该行使junit线程等到服务器线程停止。单元测试不需要这样做。
答案很长:
我们(码头开发人员)了解如何使用带有junit的jetty嵌入式服务器。
如果您有1种测试方法,或者某些要求服务器在测试方法之间保持原始状态,请使用@Before
和@After
注释来启动和停止服务器。
示例@Before / @After(Jetty 9.x):
public class MyTest
{
private Server server;
private URI serverUri;
@Before
public void startServer() throws Exception
{
this.server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(0); // let connector pick an unused port #
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
server.setHandler(context);
// Serve capture servlet
context.addServlet(new ServletHolder(new MyServlet()),"/my/*");
// Start Server
server.start();
String host = connector.getHost();
if (host == null)
{
host = "localhost";
}
int port = connector.getLocalPort();
this.serverUri = new URI(String.format("http://%s:%d/",host,port));
}
@After
public void stopServer()
{
try
{
server.stop();
}
catch (Exception e)
{
e.printStackTrace(System.err);
}
}
@Test
public void testMe()
{
// Issue request to server
URI requestUri = serverUri.resolve("/my/test");
// assert the response
}
}
这种技术使服务器在端口0上启动,这是一个神奇的数字,告诉底层堆栈选择一个空端口并开始监听。然后,测试用例会询问服务器正在侦听的端口号,并构建serverUri
字段以适合此测试运行。
这项技术效果很好,但是,它会为每种方法启动/停止服务器。
输入更好的技术,使用@BeforeClass
和@AfterClass
注释为整个测试类启动/停止服务器一次,针对此启动的服务器运行测试类内的所有方法
示例@BeforeClass / @AfterClass(Jetty 9.x):
public class MyTest
{
private static Server server;
private static URI serverUri;
@BeforeClass
public static void startServer() throws Exception
{
server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(0); // let connector pick an unused port #
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
server.setHandler(context);
// Serve capture servlet
context.addServlet(new ServletHolder(new MyServlet()),"/my/*");
// Start Server
server.start();
String host = connector.getHost();
if (host == null)
{
host = "localhost";
}
int port = connector.getLocalPort();
serverUri = new URI(String.format("http://%s:%d/",host,port));
}
@AfterClass
public static void stopServer()
{
try
{
server.stop();
}
catch (Exception e)
{
e.printStackTrace(System.err);
}
}
@Test
public void testMe()
{
// Issue request to server
URI requestUri = serverUri.resolve("/my/test");
// assert the response
}
}
看起来有多大不同?是的,变化是微妙的。 @Before
成为@BeforeClass
,@After
成为@AfterClass
。启动/停止方法现在是静态的。 server
和serverUri
字段现在是静态的。
这种技术用于我们有许多访问同一服务器的测试方法,而这些请求不会改变服务器中的状态。这样就不会在每种测试方法之间重新创建服务器,从而加快了测试用例的执行速度。
答案 1 :(得分:0)
尝试使用“com.jayway.restassured”进行http测试。太容易写一些测试:
@Test
public void testNotGetAll() {
expect().
statusCode(404).
when().
get(baseUrl+"/games/");
}
此方法调用“http://mywebserver.local:8080/rest/games/”并验证是否返回了404 http状态代码。
这种方法与Jetty服务器同步(例如)在maven生命周期的预集成测试中启动,您将完美的混合与流程集成测试相匹配!