java 在 JUnit 测试之间启动和停止 Jetty 服务器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11794405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 06:23:53  来源:igfitidea点击:

Starting and stopping a Jetty server between JUnit tests

javatestingjunitjerseyjetty

提问by Quetzalcoatl

I'm trying to simulate tests of various run-throughs of my program, setting up a Jetty server in a @Beforemethod and closing it down in an @After.

我正在尝试模拟对我的程序的各种运行的测试,在一个@Before方法中设置一个 Jetty 服务器并在一个@After.

My first test will run successfully, but upon attempting to POST data in following tests com.sun.jersey.api.client.ClientHandlerException: java.net.SocketException: Software caused connection abort: recv failedoccurs. Is there any way I can get my Server (and Client?) to shut down cleanly between tests?

我的第一个测试将成功运行,但在以下测试中尝试 POST 数据com.sun.jersey.api.client.ClientHandlerException: java.net.SocketException: Software caused connection abort: recv failed时发生。有什么方法可以让我的服务器(和客户端?)在测试之间干净利落地关闭?

My Before and After code is as follows:

我之前和之后的代码如下:

@Before
public void startServer() {
    try {
        server = new Server(8080);
        ServletContextHandler root = new ServletContextHandler(server, "/ingest", ServletContextHandler.SESSIONS);

        root.addServlet(new Servlet(), "/*");

        server.start();

        client = new Client();
        client.setChunkedEncodingSize(16 * 1024);

        FileInputStream stream = new FileInputStream(testFile);
        try {
            client.resource(uri).type(MediaType.APPLICATION_OCTET_STREAM).post(stream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Closeables.closeQuietly(stream);
            client.destroy();
        }
    } catch (Exception e) {
        e.printStackTrace();
        fail("Unexpected Exception when starting up server.");
    }
}

@After
public void shutDown() {
    if (output.exists()) {
        output.delete();
    }
    try {
        server.stop();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

采纳答案by jesse mcconnell

Best practice in testing scenarios is to not hard code the port. That only leads to conflicts when running elsewhere, especially on CI systems that have even a moderate load or variety of projects.

测试场景中的最佳实践是不对端口进行硬编码。这只会在其他地方运行时导致冲突,尤其是在具有中等负载或各种项目的 CI 系统上。

in Jetty 9 (same idea in 6, 7, 8)

在 Jetty 9(在 6、7、8 中的想法相同)

_server = new Server();
_connector = new ServerConnector(_server);  
_server.setConnectors(new Connector[] { _connector });
_server.start();
int port = _connector.getLocalPort();

回答by Quetzalcoatl

It turns out that what I had was in fact working, however due to the asynchronous nature of the server.stop(), my new server was attempting to instantiate before the previous server's shut down thread had completely executed.

事实证明,我所拥有的实际上是在工作,但是由于 的异步性质server.stop(),我的新服务器试图在前一个服务器的关闭线程完全执行之前实例化。

A simple Thread.sleep(n)after the server.stop()gives the server the time it needs to shut down between tests. Unfortunately, the server seems to prematurely claim that it has stopped thus preventing an exact solution through checking the server state - but perhaps there is something to poll on the server; possibly examining the thread pool could provide a consistent result?

一个简单的Thread.sleep(n)afterserver.stop()为服务器提供了在测试之间关闭所需的时间。不幸的是,服务器似乎过早地声称它已经停止,从而通过检查服务器状态阻止了准确的解决方案——但也许服务器上有一些东西要轮询;可能检查线程池可以提供一致的结果?

In any case, as this is only for testing purposes, merely starting the server in the @BeforeClassand shutting it down in @AfterClassprevents the whole server shut down kerfuffle, but beware of then starting another server on the same port in your test suite.

在任何情况下,由于这仅用于测试目的,因此仅在 中启动服务器并在 中@BeforeClass关闭它@AfterClass可以防止整个服务器关闭 kerfuffle,但请注意然后在测试套件的同一端口上启动另一台服务器。

回答by Kyle Winter

My guess is that it was getting a port conflict. We actually do this for our tests, and surprisingly the performance hit isn't that bad. We began by starting a single server before all tests as the answer suggests, but we had to switch to support mutation testing. One downside to relying on Maven is that you have to start it up on the side to run a single test in an IDE.

我的猜测是它遇到了端口冲突。我们实际上为我们的测试这样做了,令人惊讶的是,性能下降并没有那么糟糕。正如答案所暗示的那样,我们首先在所有测试之前启动单个服务器,但我们不得不切换到支持突变测试。依赖 Maven 的一个缺点是,您必须在 IDE 中运行单个测试的时候启动它。

For anyone interested, our implementation is here: embedded-test-jetty. It runs multiple servers at once on different ports(for parallel testing), checks port availability, supports SSL, etc.

对于任何感兴趣的人,我们的实现在这里:embedded-test-jetty。它在不同的端口上同时运行多个服务器(用于并行测试),检查端口可用性,支持 SSL 等。

回答by Andrew Mao

I handle this using a couple of things. First, after each test, make sure your server is shutdown, and join()on it. Either do this in @Afteror @AfterClassdepending on what you are doing.

我使用一些东西来处理这个问题。首先,每次测试后,请确保您的服务器已关闭,并且join()就可以了。要么根据您在做什么,@After要么@AfterClass根据您在做什么来执行此操作。

server.stop();
server.join();

Next, before each test, make sure the port is available. I use the snippet available at Sockets: Discover port availability using Java

接下来,在每次测试之前,请确保端口可用。我使用Sockets: Discover port availability using Java 中提供的片段

Then, the setup code becomes

然后,设置代码变为

public static void waitForPort(int port) {
    while( !available(port) ) {
        try { Thread.sleep(PORT_SLEEP_MILLIS); } 
        catch (InterruptedException e) {}
    }
}

@Before
public void setUp() throws Exception {
    waitForPort(9876);
    waitForPort(9877);

    // Make sure the ports are clear
    Thread.sleep(500);
}

The little extra sleepat the end ensures that the port is available; because just checking that it is available might make the system not reuse it. Another option is to just set SO_REUSEADDRwhen you are opening the port after having checked it.

最后的一点额外sleep确保端口可用;因为仅仅检查它是否可用可能会使系统无法重用它。另一种选择是SO_REUSEADDR在检查端口后打开端口时进行设置。

回答by Kkkev

I realise that this doesn't directly answer your question... but starting and stopping a server in @Beforeand @Aftermethods is inefficient when you have more than one integration test that requires a server to be running, as the server would be restarted for every test.

我意识到这并不能直接回答您的问题……但是当您有多个需要运行服务器的集成测试时,启动和停止服务器@Before@After方法的效率很低,因为每次测试都会重新启动服务器.

You may want to consider starting and stopping your server around your entire suite of tests. If you are using Maven for builds, you can do this with the combination of failsafe and Jetty plugins.

您可能需要考虑围绕整个测试套件启动和停止服务器。如果您使用 Maven 进行构建,则可以结合故障安全和 Jetty 插件来实现。

回答by Edmon

Try:

尝试:

server = new Server();
    SocketConnector connector = new SocketConnector();
    connector.setPort(8080);
    server.setConnectors(new Connector[] { connector });
    WebAppContext context = new WebAppContext();
    context.setServer(server);
    context.setContextPath("/your-context");
    context.setWar("path to war");
    server.addHandler(context);
    Thread monitor = new MonitorThread();
    monitor.start();
    server.start();
    server.join();

then somewhere you say:

然后在某处你说:

    server.stop()

Helpful article:
http://www.codeproject.com/Articles/128145/Run-Jetty-Web-Server-Within-Your-Application

有用的文章:http:
//www.codeproject.com/Articles/128145/Run-Jetty-Web-Server-Within-Your-Application