本文介绍了使用@ControllerAdvice测试@RestController的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题与测试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 .
那条线解决了我的问题.

My problem is connected with testing Spring @RestController which is also using @ControllerAdvice with @ExceptionHandler. Here is the code:

@ControllerAdvice class:

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

When using it in application everything works fine - perfectly getting 404 response with JSON explanation, but when trying to use it during tests - bad things happen.

My test class:

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

When trying to run it:

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

I think that probably MappingJackson2HttpMessageConverter is not being loaded during testing mine @ExceptionHandler (however it is configured in WebConfig.class and when trying to perform typical test - one not throwing any exception - everything works fine).

Thanks in advance for your help.

解决方案

I'm not sure if this is the best solution for this (I'd like to hear from another one),
but this is how I fix this exactly issue you are facing:

Add this line to your createExceptionResolver():

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

Something like this:

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

For some reason that I don't know, Spring was not loading my MappingJackson2HttpMessageConverter.
That line fixed my problem.

这篇关于使用@ControllerAdvice测试@RestController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 05:00
查看更多