无需致电控制器即可获得控制器建议的单元测试

时间:2019-04-14 23:06:38

标签: spring-boot controller-advice

我正在尝试为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!有什么主意吗?

1 个答案:

答案 0 :(得分:0)

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

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