java - 使用@ControllerAdvice 测试@RestController

标签 java spring junit

我的问题与测试 Spring @RestController 有关,它也使用 @ControllerAdvice 和 @ExceptionHandler。这是代码:

@ControllerAdvice 类:

@ControllerAdvice
public class MyAppExceptionHandler {

    @ExceptionHandler({ NoSuchEntityException.class })
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    public @ResponseBody
    ErrorDTO handleNotFoundException(Exception ex) throws IOException {

        return new ErrorDTO.Builder().setStatus(HttpStatus.NOT_FOUND)
                .setCause(ex.getClass().getName())
                .setThrowable(ex).build();
    }
}

在应用程序中使用它时一切正常 - 完美地获得带有 JSON 解释的 404 响应,但在测试期间尝试使用它时 - 坏事发生了。

我的测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { WebConfig.class })
@WebAppConfiguration
public class SomeTest {

    @Mock
    private SomeService service;

    @InjectMocks
    private SomeController controller;

    private MockMvc mvc;

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

    @Before
    public void setup() {

        MockitoAnnotations.initMocks(this);
        mvc = MockMvcBuilders.standaloneSetup(controller)
                .setHandlerExceptionResolvers(createExceptionResolver())
                .build();
    }

    @Test
    public void thatExceptionHappens() throws Exception {

        when(service.get(10)).thenThrow(new NoSuchEntityException(Some.class, 10));

        mvc.perform(get("/api/some/10")).andExpect(status().isNotFound());
    }
}

尝试运行时:

2014-07-15 19:35:01.376 [main] ERROR com.package.SomeTest$1 - Failed to invoke @ExceptionHandler method: public com.package.ErrorDTO com.package.MyAppExceptionHandler.handleNotFoundException(java.lang.Exception) throws java.io.IOException
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

我认为在测试我的 @ExceptionHandler 期间可能未加载 MappingJackson2HttpMessageConverter(但是它是在 WebConfig.class 中配置的,并且在尝试执行典型测试时 - 一个不抛出任何异常 - 一切正常)。

预先感谢您的帮助。

最佳答案

我不确定这是否是最好的解决方案(我想听听其他人的意见),
但这正是我解决您所面临的问题的方法:

将此行添加到您的 createExceptionResolver():

exceptionResolver.getMessageConverters().add(
        new MappingJackson2HttpMessageConverter());

像这样:

private ExceptionHandlerExceptionResolver createExceptionResolver() {
    ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
        @Override
        protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
            HandlerMethod handlerMethod, Exception exception) {
            Method method = new ExceptionHandlerMethodResolver(
                    MyAppExceptionHandler.class).resolveMethod(exception);
            return new ServletInvocableHandlerMethod(
                new MyAppExceptionHandler(), method);
        }
    };
    exceptionResolver.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
    exceptionResolver.afterPropertiesSet();
    return exceptionResolver;
}

出于某种我不知道的原因,Spring 没有加载我的 MappingJackson2HttpMessageConverter
那条线解决了我的问题。

关于java - 使用@ControllerAdvice 测试@RestController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24765219/

相关文章:

java - 测试类之间通用夹具的正确术语和最佳实践是什么?

java - 使用 Spring Data JDBC 不支持的查询参数类型?

java - 在 JSF2 中呈现 HTML5 按钮(按钮、重置和提交)

java - 两个不同 Java 程序中的加密和解密

java - 如何实现检查 Intent 是否正在运行或关闭的条件?

java - 如何在hibernate中仅删除@OneToOne双向映射的一侧

spring - Autowired 不适用于 RESTEasy 和 Spring 3

maven - 我应该在哪里放置 Junit @Category 的接口(interface)类?

java - JUnit 测试套件 : Way to create a dataset first before tests start running

java - 使用数组初始化语法有条件地添加 "optional items"?