我正在尝试使用 Mockito 对使用 @NameBinding 应用的 ContainerRequestFilter 进行单元测试。过滤器检查注释字段以确定要做什么。 查看示例代码:
注释
@Target({TYPE, METHOD})
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
MyEnum info() default MyEnum.DEFAULT;
}
我的枚举
public enum MyEnum {
VALUE1,
VALUE2,
DEFAULT
}
使用 MyEnum 作为条件的注释过滤器
@MyAnnotation
public class MyFilter implements ContainerRequestFilter {
@Context
private ResourceInfo resourceInfo;
@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
if (resourceInfo.getResourceMethod().getAnnotation(MyAnnotation.class).info().equals(MyEnum.VALUE1))
{
// set some value or throw some exception (this can be verified in the test)
}
if (resourceInfo.getResourceMethod().getAnnotation(MyAnnotation.class).info().equals(MyEnum.VALUE2))
{
// set some value or throw some exception (this can be verified in the test)
}
}
}
注释资源方法
@Path("/somepath1")
public class MyResource1
{
@GET
@MyAnnotation(info = MyEnum.VALUE1)
public Response someResourceMethod()
{
// return response
}
}
@Path("/somepath2")
public class MyResource2
{
@GET
@MyAnnotation(info = MyEnum.VALUE2)
public Response someResourceMethod()
{
// return response
}
}
这种设计使得当有新的条件要添加到过滤器时,只需添加枚举值就很容易。
如何通过改变条件中的值来对 MyFilter
进行单元测试?
我尝试的一种方法是模拟 ResourceInfo
,然后在 resourceInfo.getResourceMethod()
时返回模拟 Method
,但这无法完成,因为方法是最后一个类。
此外,不建议模拟您不拥有的对象,那么是否有不同的方法来测试它?我也不喜欢 Mockito,因此愿意接受任何其他建议。
最佳答案
最简单的方法是为测试创建一个虚拟类,并进行一些反射以获取该类的方法
@Test
public void testEnumOne() throws Exception {
Method methodOne = MockClass.class.getDeclaredMethod("enumOne");
Mockito.when(resourceInfo.getResourceMethod()).thenReturn(methodOne);
}
private static class MockClass {
@MyAnnotation(info=MyEnum.VALUE1)
public void enumOne() {}
@MyAnnotation(info=MyEnum.VALUE2)
public void enumTwo() {}
}
这是一个完整的测试。
@RunWith(MockitoJUnitRunner.class)
public class FilterAnnotationTest {
@Mock
private ResourceInfo resourceInfo;
@Mock
private ContainerRequestContext context;
@Spy
private Service service;
private MyFilter filter;
@Before
public void setUp() {
filter = new MyFilter(resourceInfo, service);
}
@Test
public void testEnumOne() throws Exception {
Method methodOne = MockClass.class.getDeclaredMethod("enumOne");
Mockito.when(resourceInfo.getResourceMethod()).thenReturn(methodOne);
filter.filter(context);
Mockito.verify(service).methodOne();
}
@Test
public void testEnumTwo() throws Exception {
Method methodTwo = MockClass.class.getDeclaredMethod("enumTwo");
Mockito.when(resourceInfo.getResourceMethod()).thenReturn(methodTwo);
filter.filter(context);
Mockito.verify(service).methodTwo();
}
private enum MyEnum {
VALUE1, VALUE2
}
@Target({ METHOD })
@Retention(RUNTIME)
private @interface MyAnnotation {
MyEnum info();
}
private static class MyFilter implements ContainerRequestFilter {
private final ResourceInfo resourceInfo;
private final Service service;
@Inject
public MyFilter(ResourceInfo resourceInfo, Service service) {
this.resourceInfo = resourceInfo;
this.service = service;
}
@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
MyAnnotation anno = resourceInfo.getResourceMethod().getAnnotation(MyAnnotation.class);
if (anno.info() == MyEnum.VALUE1) {
service.methodOne();
} else if (anno.info() == MyEnum.VALUE2) {
service.methodTwo();
}
}
}
private static class MockClass {
@MyAnnotation(info=MyEnum.VALUE1)
public void enumOne() {}
@MyAnnotation(info=MyEnum.VALUE2)
public void enumTwo() {}
}
public interface Service {
void methodOne();
void methodTwo();
}
}
关于java - 将 ResourceInfo 与 mockito 结合使用的单元测试 ContainerRequestFilter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45576542/