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