2017-08-08 26 views
2

Mockitoを使用して、@ NameBindingを使用して適用されるContainerRequestFilterのユニットテストを試みています。フィルタは、注釈フィールドをチェックして何をすべきかを決定します。 参照サンプルコード:ユニットテストContainerRequestFilter、ResourceInfoをmockitoで使用する

注釈

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

MyEnum

public enum MyEnum { 
    VALUE1, 
    VALUE2, 
    DEFAULT 
} 

条件

@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) 
     } 
    } 
} 
としてMyEnumを使用 注釈付きフィルタ

注釈付きのリソースメソッド

@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を模擬してとしたときに模擬Methodを返す試みがありましたが、これは最終的なクラスであるため実行できません。

あなたが所有していない模擬オブジェクトもお勧めできません。そのため、これをテストする別の方法がありますか?私はMockitoと結婚していないので、他の提案にも開放しています。

答えて

1

最も簡単な方法は、単なるテスト用のダミークラスを作成し、クラス

@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() {} 
} 

ここで完全なテストだ上Methodを得るために少し反射を行うことです。

@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'アノテーションを使ってセッター注入を行いました。次に、テスト設定で、 'filter.setResourceInfo(resourceInfo)'を実行しました。 – bdeo

関連する問題