My aim is to learn a little bit about mocking objects in the context of Jersey Test.
I have 3 classes:
ServiceController
package com.vogella.jersey.first;
import javax.ws.rs.*;
import javax.ws.rs.ext.Provider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ServiceController {
private static Log log = LogFactory.getLog(ServiceController.class);
public String returnSth(String inSth) {
return "returned RET" + inSth;
}
}
Hello
package com.vogella.jersey.first;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/hello")
public class Hello {
@Inject
private ServiceController serviceController;
private String inStr = "BLA";
@GET
@Produces(MediaType.TEXT_PLAIN)
public String sayPlainTextHello() {
return "Hello Jersey" + serviceController.returnSth(inStr);
}
@GET
@Produces(MediaType.TEXT_XML)
public String sayXMLHello() {
return "<?xml version="1.0"?>" + "<hello> Hello Jersey" + "</hello>";
}
@GET
@Produces(MediaType.TEXT_HTML)
public String sayHtmlHello() {
return "<html> " + "<title>" + "Hello Jersey" + "</title>"
+ "<body><h1>" + "Hello Jersey" + serviceController.returnSth(inStr) + "</body></h1>" + "</html> ";
}
}
HelloTest
package com.vogella.jersey.first;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.jupiter.api.Test;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.*;
class HelloTest extends JerseyTest {
private ServiceController serviceController;
@Override
protected Application configure() {
ResourceConfig config = new ResourceConfig(Hello.class);
serviceController = mock(ServiceController.class);
config.register(new AbstractBinder() {
@Override
protected void configure() {
bind(ServiceController.class).to(ServiceController.class);
}
}
);
return config;
}
@Test
public void helloResponseCodeOK() {
Response response = target("hello").request()
.get();
assertEquals("Http Response should be 200: ", Response.Status.OK.getStatusCode(), response.getStatus());
}
@Test
public void helloResponseTextIsCorrect() {
when(serviceController.returnSth(any(String.class))).thenReturn("RetFromMock");
Response response = target("hello").request(MediaType.TEXT_PLAIN)
.get();
assertTrue("Hello Jerseyreturned RETBLA".equals(response.readEntity(String.class)));
}
}
So in the Hello class there is a “hello” endpoint and in 2 methods there is a call to a “returnSth” method from the injected ServiceController.
In HelloTest I wanted to test the “hello” endpoint but without calling the real serviceController.returnSth method – instead wanted to mock it and return some other string – “RetFromMock” regardless of the input.
However during the test execution the mocking is ineffective and still the real one is getting called. I would expect the assertTrue to fail, because if the mock would get called, the response output should be “Hello JerseyRetFromMock” but is always “Hello Jerseyreturned RETBLA”.
I was trying different ways of instantiating the mock:
Injecting:
@Inject
private ServiceController serviceController;
Mocking with annotations:
@Mock
private ServiceController serviceController;
@InjectMocks
private ServiceController serviceController;
Those attempts were resulting in NullPointerException (serviceController was null).
The above I tried also with @RunWith(MockitoJUnitRunner.class) annotation with the same result.
I also tried to follow the example from this link:
https://medium.com/@mnu/overriding-dependency-injection-with-hk2-in-jersey-tests-4756144c2399
but was never able to get the “bind(serviceController).to(ServiceController.class)” to work – failing with IllegalArgumentException.