Here is the source code:
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);
}
}
}
The test code:
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();
}
}
I want to test the class WebServer, and make sure that it calls method start() from Server dependency(from Jetty library). The source code works and the test is simple and should just check that the method on the mock is called.
But then I am getting back java.lang.NullPointerException when it hits "server.start()".
Looking at the source code of jetty, the start() method is final, throws an exception and comes from a parent class "AbstractLifeCycle" which is inherited by "Server" class.
What am I missing? How can I get this test to work? Is it due to the Exception being thrown by Server.start()? Is it something to do with verifying inherited methods (Although I tried this using some dummy classes and it was not a problem)?
I have done the same code, but instead of using Jetty, i have used an interface, and the tests pass.
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);
}
}
}
and interface
public interface Server {
void start();
DatagramSocket getURI();
}
and test code
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();
}
}
So it feels like something internal to how jetty implements start() and/or how mockito mocks the Server class
The stack trace is
java.lang.NullPointerException at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:61) at com.hanfak.greedydb.infrastructure.entrypoints.rest.JettyWebServerTest.shouldStartJettyServer(JettyWebServerTest.java:57) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
private final Server server = mock(Server.class);
This line initializes the mock. I want to verify the method start() is called from the mock. The start() method return type is void, so no behaviour returned thus no when().thenReturn() – caniMockitoAnnotations.initMocks
then you're probably trying to force@Mock
and@Spy
etc to work, not get a plain mock to work. The above code correctly instantiates mocks. TheMockitoJUnitRunner
would be nicer, but it's not the root of the problem. – Ashley Frieze