这是源代码:
import org.eclipse.jetty.server.Server;
public class WebServer {
private final Server server;
public WebServer(Server server) {
this.server = server;
}
public WebServer() {
this(new Server(1234));
}
public void start() {
try {
server.start();
} catch (Exception e) {
throw new IllegalStateException(format("Could not start server on port '%d'", server.getURI().getPort()), e);
}
}
public void stop() {
try {
server.stop();
} catch (Exception e) {
throw new IllegalStateException(format("Could not stop server on port '%d'", server.getURI().getPort()), e);
}
}
}
测试代码:
import org.eclipse.jetty.server.Server;
public class WebServerTest implements WithAssertions {
private final Server server = mock(Server.class);
private final WebServer webServer = new WebServer(server);
@Test
public void shouldStartJettyServer() throws Exception {
webServer.start();
verify(server).start();
}
}
我想测试类WebServer,并确保它从服务器依赖项(来自Jetty库)中调用方法start()。源代码可以正常工作,并且测试很简单,应该只检查该模拟方法是否已调用。
但是当我碰到“ server.start()”时,我又重新获得了java.lang.NullPointerException。
看看jetty的源代码,start()方法是最终的,引发异常,并来自“服务器”类继承的父类“ AbstractLifeCycle”。
我想念什么?我怎样才能使该测试正常工作?是由于Server.start()引发了异常吗?与验证继承的方法有关(尽管我使用一些虚拟类进行了尝试,但这不是问题)?
我已经完成了相同的代码,但是我没有使用Jetty,而是使用了一个接口,并且测试通过了。
public class WebServer {
private final Server server;
public WebServer(Server server) {
this.server = server;
}
public void startServer() {
try {
this.server.start();
} catch (Exception e) {
throw new IllegalStateException(format("Could not startServer server on port '%d'", this.server.getURI().getPort()), e);
}
}
}
和界面
public interface Server {
void start();
DatagramSocket getURI();
}
和测试代码
public class WebServerTest {
private final Server server = mock(Server.class);
private final WebServer webServer = new WebServer(server);
@Test
public void blah() throws Exception {
webServer.startServer();
verify(server).start();
}
}
因此,感觉就像码头如何实现start()和/或Mockito模拟Server类的内部
堆栈跟踪为
java.lang.NullPointerException 在org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:61) 在com.hanfak.greedydb.infrastructure.entrypoints.rest.JettyWebServerTest.shouldStartJettyServer(JettyWebServerTest.java:57)处 在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处 在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect.Method.invoke(Method.java:498) 在org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall(FrameworkMethod.java:50) 在org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 在org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 在org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 在org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 在org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:290) 在org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:71) 在org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 在org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:58) 在org.junit.runners.ParentRunner上$ 2.evaluate(ParentRunner.java:268) 在org.junit.runners.ParentRunner.run(ParentRunner.java:363) 在org.junit.runner.JUnitCore.run(JUnitCore.java:137) 在com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 在com.intellij.rt.execution.junit.IdeaTestRunner $ Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) 在com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) 在com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
答案 0 :(得分:0)
此问题的根本原因似乎是Jetty的日志记录输出包含server.getURI().getPort()
。您的模拟游戏会将null
返回您尚未设置要返回的所有内容。如果您在测试设置中添加了when(server.getURI()).thenReturn(someUri)
,则可能会开始起作用。
答案 1 :(得分:0)
经过调查。我发现Jetty Server类从AbstractLifeCycle类继承了start()方法。此启动方法被声明为final。因此,mockito无法嘲笑这一点。
我发现使用此版本的Mockito(即Mocktio 2),请参见下面的Maven导入
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
我现在可以运行测试,它将模拟它,并且上面的测试将通过。
以下是该库的文档:https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#unmockable
课程:声明为final的任何方法或类都无法模拟。