我正在尝试为Jersey使用Grizzly和Mockito编写集成测试用例,Spring,我无法模拟服务类。如何模拟使用@AutoWired
在我的Resource类中注入的服务类@AutoWired
MyFirstService myFirstServiceImpl;
@AutoWired
MySecondService mySecondServiceImpl;
@GET
@Path("/abc")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getDetails(@QueryParam("xyz") String xyz,
@QueryParam("pqr") String pqr) {
Gson gson = new Gson();
Map<String, Object> someMap= new HashMap<String, Object>();
try {
map.put("a", myFirstServiceImpl.getSomeDetails(xyz);
map.put("b", mySecondService.getSomeMoreDetails(pqr);
} catch (Exception e) {
e.printStackTrace();
}
return Response.status(200).entity(gson.toJson(someMap)).build();
}
Test Class:
@Mock
private static MySecondService mySecondServiceImpl;;
@Mock
private static MyFirstService myFirstServiceImpl;
@Before
public void initMocks() {
resource = new MyResource();
MockitoAnnotations.initMocks(this);
resource.setMyFirstService (firstService);
resource.setSecondService(secondService);
}
@Override
protected TestContainerFactory getTestContainerFactory() {
return new GrizzlyWebTestContainerFactory();
}
private DeploymentContext getRestResourcesWithFilter() {
System.setProperty("jersey.config.test.container.port", "8104");
ServletDeploymentContext context =
ServletDeploymentContext
.forServlet(
new ServletContainer(new ResourceConfig(MyResource.class).property(
ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true")))
.addListener(ContextLoaderListener.class).addListener(RequestContextListener.class)
.initParam("contextConfigLocation", "classpath:applicationContext.xml")
.build();
return context;
@Test
public void test() throws Exception {
SomeOBject object= new SomeObject();
Object2 obj= new Object2();
when(myFirstServiceImpl.getSomeDetails(any(String.class))).thenReturn(object);
when(mySecondService.getSomeMoreDetails(pqr)).thenReturn(obj);
Response response = target("v1/abc").request().get();
}
这个测试用例正在传递,但我嘲笑的服务类没有嘲笑当代码命中该行时我得到空指针异常
答案 0 :(得分:2)
所以有几个问题
@Before
方法。 JerseyTest
已经implements a @Before
method,它创建了测试容器。因此,您的模拟将不会及时创建,服务将为null。最好的办法是在configureDeployment()
方法中创建服务,在那里初始化Jersey应用程序。将为每个测试用例创建一个新容器,因此每次测试都会有新的模拟。
您可以将类简单地传递给ResourceConfig
构造函数,这将导致Jersey运行时创建资源类的实例。因此,在创建资源类之后,请new ResourceConfig(MyResource.class)
而不是new ResourceConfig().register(resource)
。
因此configureDeployment()
方法应该更像
@Override
public DeploymentContext configureDeployment() {
resource = new MyResource();
MockitoAnnotations.initMocks(this);
resource.setMyFirstService(firstService);
resource.setSecondService(secondService);
ServletDeploymentContext context
= ServletDeploymentContext.forServlet(
new ServletContainer(new ResourceConfig().register(resource).property(
ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true")))
.build();
return context;
}
另一个问题是您实际上并未在请求中传递任何查询参数。因此,在您的资源方法中,参数将为null。您的请求应该更像
target(...).queryParam(key1, value1).queryParam(key2, value2)
这是一个完整的测试
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import junit.framework.Assert;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class MockitoTest extends JerseyTest {
public static interface Service {
String getMessage(String name);
}
@Mock
private Service service;
@Path("mock")
public static class MyResource {
private Service service;
public void setService(Service service) {
this.service = service;
}
@GET
public String get(@QueryParam("name") String name) {
return service.getMessage(name);
}
}
@Override
public DeploymentContext configureDeployment() {
MyResource resource = new MyResource();
MockitoAnnotations.initMocks(this);
resource.setService(service);
ServletDeploymentContext context
= ServletDeploymentContext.forServlet(
new ServletContainer(new ResourceConfig().register(resource).property(
ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true")))
.build();
return context;
}
@Override
protected TestContainerFactory getTestContainerFactory() {
return new GrizzlyWebTestContainerFactory();
}
@Test
public void doTest() {
Mockito.when(service.getMessage(Mockito.anyString())).thenAnswer(new Answer<String>(){
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
return "Hello " + (String)invocation.getArguments()[0];
}
});
Response response = target("mock").queryParam("name", "peeskillet").request().get();
Assert.assertEquals(200, response.getStatus());
String message = response.readEntity(String.class);
Assert.assertEquals("Hello peeskillet", message);
System.out.println(message);
}
}