Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Annotation based RequestInterceptor

I wanted to do so custom logic(Record the request and response) on some routes. Based on some research I came decided to use AnnotationBased RequestInterceptor. This is my code for interceptor.

public class CustomInterceptor extends HandlerInterceptorAdapter {
@Override
public void afterCompletion(final HttpServletRequest request,
                            final HttpServletResponse response,
                            final Object handler,
                            final Exception ex) {
     if (handler != null && handler instanceof  HandlerMethod) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        CustomRecord annotation = AnnotationUtils.getAnnotation(handlerMethod.getMethod(), CustomRecord.class);
        if (annotation != null) {
              // Record Request and Response in a File.
        }
}

Now this class is working as expected but I was unable to unit test this function.

  • I first thought of trying a creating an HandlerMethod Object but I did not get anywhere.
  • Second I tried to use PowerMokito. This was my test code:

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(CustomInterceptor.class)
    @PowerMockIgnore("javax.management.*")
    public class CustomInterceptorTest {
    @Test
    public void restAnnotationRecording_negetivecase() {
      HandlerMethod mockHandler = mock(HandlerMethod.class);
      PowerMockito.mockStatic(AnnotationUtils.class);
      when(AnnotationUtils.getAnnotation(mockHandler.getMethod(), 
           CustomRecord.class).thenReturn(null);
      // Verify file is not saved
    }
     // A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() methodcannot be saved.
    @Test
    public void restAnnotationRecording_happycase() {
        HandlerMethod mockHandler = mock(HandlerMethod.class);
        PowerMockito.mockStatic(AnnotationUtils.class);
        when(AnnotationUtils.getAnnotation(mockHandler.getMethod(), CustomRecord.class).thenReturn(mockAnnotation);
        // Verify file is saved
    }
    }
    
    • This gives an Error A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies with doReturn|Throw() family of methods.

I wanted to check if there is any method to test the Interceptor. I am a newbie in Java, thanks for help.

like image 807
ayushmad Avatar asked Aug 04 '18 04:08

ayushmad


1 Answers

You can easily create your own HandlerMethod without mocking. There's a constructor that accepts an Object (the controller) and a Method (the controller method). The easiest way to get a Method is to simply call Class.getMethod(). What you want to do is just create a dummy controller class, and then use that class to get the method. For example

class TestController {
    @Custom
    public void testMethod() {}
}

Method method = TestController.class.getMethod("testMethod");
TestController controller = new TestController();
HandlerMethod handlerMethod = new HandlerMethod(controller, method);

Custom annotation = handlerMethod.getMethodAnnotation(Custom.class);

It's that easy. Below is a complete test.

public class HandlerInterceptorTest {

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    private @interface Custom {
    }

    private static class MyHandlerInterceptor implements HandlerInterceptor {

        @Override
        public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
            if (handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                Custom annotation = handlerMethod.getMethodAnnotation(Custom.class);
                if (annotation != null) {
                    return true;
                }
            }
            return false;
        }
    }

    private static class TestController {
        @Custom
        public void testMethodWithAnnotation() {}

        public void testMethodWithoutAnnotation() {}
    }

    @Test
    public void testMethodWithAnnotation() throws Exception {
        Method method = TestController.class.getMethod("testMethodWithAnnotation");
        TestController controller = new TestController();
        HandlerMethod handlerMethod = new HandlerMethod(controller, method);

        MyHandlerInterceptor interceptor = new MyHandlerInterceptor();
        boolean result = interceptor.preHandle(null, null, handlerMethod);

        assertTrue(result);
    }

    @Test
    public void testMethodWithoutAnnotation() throws Exception {
        Method method = TestController.class.getMethod("testMethodWithoutAnnotation");
        TestController controller = new TestController();
        HandlerMethod handlerMethod = new HandlerMethod(controller, method);

        MyHandlerInterceptor interceptor = new MyHandlerInterceptor();
        boolean result = interceptor.preHandle(null, null, handlerMethod);

        assertFalse(result);
    }
}
like image 54
Paul Samsotha Avatar answered Sep 19 '22 23:09

Paul Samsotha