2

統合 JUnit テストを書いています。私の仕事は、ローカル サーバーの応答が正しいかどうかをテストすることです。上記のサーバーは、分析するページのアドレスを GET パラメータとして受け取ります (例: localhost:8000/test?url=http://www.example.com)。

www.example.com に依存することを避けるために、この特定のテストのために、常に同じコンテンツを提供する独自の jetty サーバーを開始したいと考えています。

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が呼び出されることはありません。これが機能しない理由について何か提案はありますか?

PS削除server.stop()してブラウザで入力するとhttp://localhost:8080、適切なページが表示されます。

4

2 に答える 2

5

素早い回答:

行を削除しserver.join()ます。その行は、サーバースレッドが停止するまでjunitスレッドを待機させます。単体テストには必要ありません。

長い答え:

私たち (jetty 開発者) が 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アノテーションを使用して、テスト クラス全体に対してサーバーを 1 回起動/停止し、この起動されたサーバーに対してテスト クラス内のすべてのメソッドを実行します。

例 @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なりました。start/stop メソッドは静的になりました。およびフィールドは静的になりました。@BeforeClass@After@AfterClassserverserverUri

この手法は、同じサーバーにアクセスする多数のテスト メソッドがあり、それらの要求がサーバーの状態を変更しない場合に使用されます。これにより、各テスト メソッド間でサーバーを再作成しないだけで、テスト ケースの実行が高速化されます。

于 2013-10-01T12:36:09.383 に答える
0

http テスト用に「com.jayway.restassured」を試してみてください。いくつかのテストを書くのは簡単すぎる:

@Test
public void testNotGetAll() {
    expect().
        statusCode(404).
    when().
        get(baseUrl+"/games/");
}

このメソッドは「http://mywebserver.local:8080/rest/games/」を呼び出し、404 http ステータス コードが返されることを確認します。

そして、このアプローチは、(たとえば) Maven ライフサイクルの pre-integration-test で開始された Jetty サーバーと同期され、統合テストを処理するための完璧な組み合わせに一致します。

于 2014-04-10T01:32:17.087 に答える