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

Java 在JUnit测试之间启动和停止Jetty服务器,java,testing,junit,jersey,jetty,Java,Testing,Junit,Jersey,Jetty,我试图模拟我的程序的各种运行测试,在@Before方法中设置Jetty服务器,并在@After方法中关闭它 我的第一个测试将成功运行,但在尝试在以下测试中发布数据时,com.sun.jersey.api.client.clienthandler异常:java.net.SocketException:软件导致的连接中止:recv失败。有没有办法让我的服务器(和客户端?)在测试之间完全关闭 我的前后代码如下: @Before public void startServer() { try {

我试图模拟我的程序的各种运行测试,在
@Before
方法中设置Jetty服务器,并在
@After
方法中关闭它

我的第一个测试将成功运行,但在尝试在以下测试中发布数据时,
com.sun.jersey.api.client.clienthandler异常:java.net.SocketException:软件导致的连接中止:recv失败
。有没有办法让我的服务器(和客户端?)在测试之间完全关闭

我的前后代码如下:

@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();
    }
}
尝试:

然后你会说:

    server.stop()
有用文章:

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

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


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

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


<>你可能会考虑在整个测试过程中启动和停止服务器。如果您正在使用Maven进行构建,您可以结合故障保护和Jetty插件来实现这一点。

我猜是因为端口冲突。我们实际上是在测试中这样做的,令人惊讶的是,性能的影响并没有那么糟糕。正如答案所示,我们开始在所有测试之前启动一台服务器,但我们不得不转而支持突变测试。依赖Maven的一个缺点是,您必须在侧面启动它才能在IDE中运行单个测试


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

我使用一些方法来处理这一问题。首先,在每次测试之后,确保您的服务器已关闭,并在服务器上执行
join()
。在
@After
@AfterClass
中执行此操作,具体取决于您正在执行的操作

server.stop();
server.join();
接下来,在每次测试之前,确保端口可用。我使用

然后,设置代码变为

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);
}

最后一点额外的
睡眠
,确保端口可用;因为仅仅检查它是否可用可能会使系统无法重用它。另一个选项是,在检查完端口后打开端口时,只需设置
以便_REUSEADDR

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

在9号码头(与6、7、8号码头的想法相同)


请参阅将Jetty与Failsafe.imho一起使用的示例,询问是否有人对代码解决方案感兴趣是没有意义的,如果您认为它是相关的,只需将其挂起,不要问:)。如果它太长,你可以将链接放到你的回购协议中。我不确定我们什么时候可以把它移出我们的内部回购协议-但它现在在上面:)你可能只想使用
server.join()
等待它停止。对于Jetty 6,我必须使用SelectChannelConnector(ServerConnector不存在)。
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);
}
_server = new Server();
_connector = new ServerConnector(_server);  
_server.setConnectors(new Connector[] { _connector });
_server.start();
int port = _connector.getLocalPort();