2

我正在编写集成 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();
}

每次我执行这个测试时,永远不会调用handlein 的方法。MockPageHandler你有什么建议为什么这不起作用?

PS当我删除server.stop()并在浏览器类型http://localhost:8080中显示正确的页面。

4

2 回答 2

5

快速回答:

删除server.join()线。该行使 junit 线程等待,直到服务器线程停止。单元测试不需要它。

长答案:

我们(jetty 开发人员)已经了解了将 jetty 嵌入式服务器与 junit 一起使用的知识。

如果您有 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。开始/停止方法现在是静态的。serverserverUri字段现在是静态的。

这种技术用于我们有几十个访问同一服务器的测试方法,并且这些请求不会改变服务器中的状态。这通过简单地不在每个测试方法之间重新创建服务器来加速测试用例的执行。

于 2013-10-01T12:36:09.383 回答
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 生命周期的预集成测试开始,您将完美的组合匹配到流程集成测试!

于 2014-04-10T01:32:17.087 回答