我能够创建以下基类,以实现 OP 之间的集成JerseyTest
,Mockito
例如:
package org.itest;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.test.JerseyTestNg;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.util.ReflectionUtils;
import javax.ws.rs.core.Application;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Nom1fan
*/
public abstract class JerseyTestBase extends JerseyTestNg.ContainerPerClassTest {
@Override
protected Application configure() {
MockitoAnnotations.openMocks(this);
ResourceConfig application = new ResourceConfig();
Object resourceUnderTest = getResourceUnderTest();
application.register(resourceUnderTest);
Map<String, Object> properties = Maps.newHashMap();
properties.put(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
properties.put("contextConfigLocation", "classpath:applicationContext.xml");
// Retrieve the fields annotated on subclass as @Mock via reflection and keep each instance
// and its type on an entry in the map, later used to bind to Jersey infra.
HashMap<Object, Class<?>> mocksToBindMap = Maps.newHashMap();
List<Field> fieldsWithMockAnnotation = FieldUtils.getFieldsListWithAnnotation(getClass(), Mock.class);
for (Field declaredField : fieldsWithMockAnnotation) {
declaredField.setAccessible(true);
Object fieldObj = ReflectionUtils.getField(declaredField, this);
mocksToBindMap.put(fieldObj, declaredField.getType());
}
application.setProperties(properties);
application.register(new AbstractBinder() {
@Override
protected void configure() {
for (Map.Entry<Object, Class<?>> mockToBind : mocksToBindMap.entrySet()) {
bind(mockToBind.getKey()).to(mockToBind.getValue());
}
}
});
return application;
}
protected abstract Object getResourceUnderTest();
}
钩子getResourceUnderTest
必须由扩展测试类实现,提供它希望测试的资源实例。
测试类示例:
import org.itest.JerseyTestBase;
import org.mockito.InjectMocks;
import org.mockito.Mock;
public class MyJerseyTest extends JerseyTestBase {
@Mock
private MockA mockA;
@Mock
private MockB mockB;
@InjectMocks
private MyResource myResource;
@Override
protected Object getResourceUnderTest() {
return myResource;
}
@Test
public void myTest() {
when(mockA.foo()).thenReturn("Don't you dare go hollow");
when(mockB.bar()).thenReturn("Praise the Sun \\[T]/");
// Test stuff
target("url...").request()...
}
}
MyResource 类看起来像这样:
@Path("url...")
@Controller
public class MyResource {
private final MockA mockA;
private final MockB mockB;
@Autowired // Mocks should get injected here
public MyResource(MockA mockA, MockB mockB) {
this.mockA = mockA;
this.mockB = mockB;
}
@GET
public Response someAPI() {
mockA.foo();
mockB.bar();
}
}
注意:我使用 Spring 和 Apache 的反射工具使事情变得更容易,但这不是强制性的。可以手写的简单反射代码。