快速回答:
删除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
。开始/停止方法现在是静态的。server
和serverUri
字段现在是静态的。
这种技术用于我们有几十个访问同一服务器的测试方法,并且这些请求不会改变服务器中的状态。这通过简单地不在每个测试方法之间重新创建服务器来加速测试用例的执行。