首页 > 解决方案 > Unit Test for a Controller Advice without calling the controller

问题描述

I'm trying to write a unit test for a controllerAdvice, all the example I saw in the net are for an integration test, that's mean they are calling their main Rest controller and I dont want to do in that way. here is the test i'm trying to write :

public class ExceptionTest {

    private MockHttpServletRequest servletRequest;

    private MockHttpServletResponse servletResponse;

    @Before
    public void setup() {
        this.servletRequest = new MockHttpServletRequest("GET", "/");
        this.servletResponse = new MockHttpServletResponse();
 }


    @Test
    public void controllerAdviceExceptionHandlerExceptionResolverTest () throws UnsupportedEncodingException {


        StaticWebApplicationContext ctx = new StaticWebApplicationContext();
        ctx.registerSingleton("exceptionHandler", MyControllerAdvice.class);
        ctx.refresh();

        ExceptionHandlerExceptionResolver resolver = createExceptionResolver();
        resolver.setApplicationContext(ctx);

        ServletRequestBindingException ex = new ServletRequestBindingException("message");
        Assert.assertNotNull(resolver.resolveException(this.servletRequest, this.servletResponse, null, ex));

    }

    private ExceptionHandlerExceptionResolver createExceptionResolver() {
        ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
            protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception) {
                Method method = new ExceptionHandlerMethodResolver(MyControllerAdvice.class).resolveMethod(exception);
                return new ServletInvocableHandlerMethod(new MyControllerAdvice(), method);
            }
        };
        exceptionResolver.afterPropertiesSet();
        return exceptionResolver;
    }

My issue is that the resolver.resolveException(this.servletRequest, this.servletResponse, null, ex) is returning null however it should not! any idea ?

标签: spring-bootcontroller-advice

解决方案


To resolve my issue I created a mocked controller that inject a given exception and throw it..

@Controller
class MockedTestController {

    private Throwable exception;

    void setException(Throwable exception) {
        this.exception = exception;
    }

    @GetMapping
    public void handle() throws Throwable {
        if (this.exception != null) {
            throw this.exception;
        }
    }
}

than I setup my unit test as follow :

@Before
public void setup() {
    mockMvc = MockMvcBuilders.standaloneSetup(controller)
            .setControllerAdvice(cspControllerAdvice)
            .build();
}

the test can be as follow :

@Test
public void given_MyException_return_Error_with_values() throws Exception {

    controller.setException(new MyException(""));
    assertExceptionHandler(....);

}

where

private void assertExceptionHandler(...) throws Exception {
    mockMvc.perform(MockMvcRequestBuilders.get("/"))
            .andExpect(...);
}

推荐阅读