vendredi 8 juillet 2016

How do I mock a Resource in ControllerAdvice class while testing Spring Exception handling with Mockito

I have a simple test for Spring Exception handling that I am running with Mockito

Here is my test:

@RunWith(MockitoJUnitRunner.class)
public class ControllerTest {

    @Mock
    private InputValidationService service;

    @Resource
    private ErrorHelper errorHelper;

    @InjectMocks
    private RestController controller;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.standaloneSetup(controller)
                .setHandlerExceptionResolvers(withExceptionControllerAdvice())
                .setMessageConverters(new MappingJackson2HttpMessageConverter()).build();
    }

    private ExceptionHandlerExceptionResolver withExceptionControllerAdvice() {
        final ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
            @Override
            protected ServletInvocableHandlerMethod getExceptionHandlerMethod(final HandlerMethod handlerMethod,
                                                                              final Exception exception) {
                Method method = new ExceptionHandlerMethodResolver(RestControllerAdvice.class).resolveMethod(exception);
                if (method != null) {
                    return new ServletInvocableHandlerMethod(new RestControllerAdvice(), method);
                }
                return super.getExceptionHandlerMethod(handlerMethod, exception);
            }
        };
        exceptionResolver.afterPropertiesSet();
        return exceptionResolver;
    }

    @Test
    public void thatExceptionHappens() throws Exception {
        doThrow(new ConstraintViolationException(new HashSet<ConstraintViolation<?>>())).when(service).validateRequest(anyString());
        MvcResult mvcResult = mockMvc.perform(get("/employee/details/9876")).andDo(print()).andExpect(status().isOk()).andReturn();
        System.out.print("");
    }
} 

And here is my ControllerAdvice:

@ControllerAdvice
    public class RestControllerAdvice {

        @Resource
        private ErrorHandler errorHandler;

        @ExceptionHandler(value = { ConstraintViolationException.class })
        @ResponseStatus(value = HttpStatus.BAD_REQUEST)
        @ResponseBody
        public ServiceError handleConstraintViolations(ConstraintViolationException e) {
            Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
            return errorHandler.buildResponseFromViolations(violations);
        }
    } 

The exception is thrown correctly and even the ControllerAdvice is called correctly based on the ConstraintViolationException thrown, but I am facing issue mocking the errorHandler in the RestControllerAdvice -- It throws a NullPointerException as it is not getting injected or mocked..

I tried to add the following in my test

@Mock
ErrorHandler errorHandler;

@Resource
ErrorHandler errorHandler

But nothing seems to work, everytime the execution reaches the errorHandler.buildResponseFromViolations(); It is NULL!!

So how do I mock the

@Resource
ErrorHandler errorHandler;

just like I mocked the

@Mock
InputValidationService service;

Here is some additional info:

InputValidationService is Auto-Wired in the RestController where ErrorHandler is a Resource in ControllerAdvice.

I am struggling with this for past few hours and tried every possible to re-building my unit test. Please help me with this.

Aucun commentaire:

Enregistrer un commentaire