在不调用控制器的情况下对控制器建议进行单元测试

Unit Test for a Controller Advice without calling the controller

我正在尝试为 controllerAdvice 编写单元测试,我在网上看到的所有示例都是针对集成测试的,这意味着他们正在调用他们的主要 Rest 控制器,而我不想那样做. 这是我要写的测试:

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;
    }

我的问题是 resolver.resolveException(this.servletRequest, this.servletResponse, null, ex) 返回 null 但它不应该返回 null!有什么想法吗?

为了解决我的问题,我创建了一个模拟控制器,它注入一个给定的异常并抛出它..

@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;
        }
    }
}

我的单元测试设置如下:

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

测试可以如下:

@Test
public void given_MyException_return_Error_with_values() throws Exception {

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

}

其中

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