2017-08-08 145 views
2

我正在嘗試使用Mockito來單元測試使用@NameBinding應用的ContainerRequestFilter。篩選器檢查註釋字段以確定要執行的操作。 見示例代碼:單元測試ContainerRequestFilter與mockito使用ResourceInfo

註釋

@Target({TYPE, METHOD}) 
@NameBinding 
@Retention(RetentionPolicy.RUNTIME) 
public @interface MyAnnotation { 
    MyEnum info() default MyEnum.DEFAULT; 
} 

MyEnum

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,但由於Method是最終的類,因此無法完成此操作。

也不建議嘲笑你不擁有的對象,那麼有沒有不同的方法來測試它?我也不喜歡Mockito,所以對其他建議敞開心扉。

回答

1

最簡單的方法是剛剛創建的測試虛擬類,並做一些思考,以獲得Method的類

@Test 
public void testEnumOne() throws Exception { 
    Method methodOne = MockClass.class.getMethod("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.getMethod("enumOne"); 
     Mockito.when(resourceInfo.getResourceMethod()).thenReturn(methodOne); 

     filter.filter(context); 
     Mockito.verify(service).methodOne(); 
    } 

    @Test 
    public void testEnumTwo() throws Exception { 
     Method methodTwo = MockClass.class.getMethod("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(); 
    } 
} 
+0

這工作完美。我正在使用Guice,並且必須在'MyFilter'構造函數中注入另一個依賴項。因此,對'ResourceInfo'的'@ Context'註釋使用了setter注入。然後在測試設置中,做了'filter.setResourceInfo(resourceInfo)' – bdeo

相關問題