java - 将 ResourceInfo 与 mockito 结合使用的单元测试 ContainerRequestFilter

标签 java unit-testing jersey jax-rs mockito

我正在尝试使用 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/

相关文章:

java - 为链表对象编写 equals() 方法

java - 寻找哈密顿路径和哈密顿循环

c# - NUnit - 断言异常和属性

c# - 不确定如何模拟 INancyModule.View 方法?

java - 使用 graphdb 在节点之间建立关系

Java:为什么这个4个字符的字符串会创建一个包含6个数据的byte[]?

java - 使用来自不同类加载器的键的 EnumMap 的奇怪行为

android - 使用mockito测试void方法

java - 在 Jersey 中,我可以将 QueryParams 和 FormParams 组合成一个方法的值吗?

java - Jersey 两种资源的相同路径