복붙노트

[SPRING] Spring MVC 테스트 @ExceptionHandler 메소드

SPRING

Spring MVC 테스트 @ExceptionHandler 메소드

예기치 않은 예외를 잡기 위해 다음과 같은 간단한 컨트롤러가 있습니다.

@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(Throwable.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ResponseEntity handleException(Throwable ex) {
        return ResponseEntityFactory.internalServerErrorResponse("Unexpected error has occurred.", ex);
    }
}

Spring MVC Test 프레임 워크를 사용하여 통합 테스트를 작성하려고합니다. 이것은 내가 지금까지 가지고있는 것이다 :

@RunWith(MockitoJUnitRunner.class)
public class ExceptionControllerTest {
    private MockMvc mockMvc;

    @Mock
    private StatusController statusController;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.standaloneSetup(new ExceptionController(), statusController).build();
    }

    @Test
    public void checkUnexpectedExceptionsAreCaughtAndStatusCode500IsReturnedInResponse() throws Exception {

        when(statusController.checkHealth()).thenThrow(new RuntimeException("Unexpected Exception"));

        mockMvc.perform(get("/api/status"))
                .andDo(print())
                .andExpect(status().isInternalServerError())
                .andExpect(jsonPath("$.error").value("Unexpected Exception"));
    }
}

Spring MVC 인프라에서 ExceptionController와 mock StatusController를 등록한다. 테스트 메서드에서 나는 StatusController로부터 예외를 던질 것을 기대했다.

예외가 발생하지만 ExceptionController가 처리하지 않습니다.

ExceptionController가 예외를 얻고 적절한 응답을 리턴하는지 테스트 할 수 있기를 원합니다.

왜 이것이 작동하지 않는지에 대한 생각과 이런 종류의 테스트를 어떻게해야합니까?

감사.

해결법

  1. ==============================

    1.나는 지금 막 동일한 문제 및 뒤에 오는 일이 저를 위해 있었다 :

    나는 지금 막 동일한 문제 및 뒤에 오는 일이 저를 위해 있었다 :

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.standaloneSetup(statusController)
             .setControllerAdvice(new ExceptionController())
            .build();
    }
    
  2. ==============================

    2.이 코드는 예외 제어 된 조언을 사용할 수있는 기능을 추가합니다.

    이 코드는 예외 제어 된 조언을 사용할 수있는 기능을 추가합니다.

    @Before
    public void setup() {
        this.mockMvc = standaloneSetup(commandsController)
            .setHandlerExceptionResolvers(withExceptionControllerAdvice())
            .setMessageConverters(new MappingJackson2HttpMessageConverter()).build();
    }
    
    private ExceptionHandlerExceptionResolver withExceptionControllerAdvice() {
        final ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
            @Override
            protected ServletInvocableHandlerMethod getExceptionHandlerMethod(final HandlerMethod handlerMethod,
                final Exception exception) {
                Method method = new ExceptionHandlerMethodResolver(ExceptionController.class).resolveMethod(exception);
                if (method != null) {
                    return new ServletInvocableHandlerMethod(new ExceptionController(), method);
                }
                return super.getExceptionHandlerMethod(handlerMethod, exception);
            }
        };
        exceptionResolver.afterPropertiesSet();
        return exceptionResolver;
    }
    
  3. ==============================

    3.독립 실행 형 설치 테스트를 사용하고 있으므로 수동으로 예외 처리기를 제공해야합니다.

    독립 실행 형 설치 테스트를 사용하고 있으므로 수동으로 예외 처리기를 제공해야합니다.

    mockMvc= MockMvcBuilders.standaloneSetup(adminCategoryController).setSingleView(view)
            .setHandlerExceptionResolvers(getSimpleMappingExceptionResolver()).build();
    

    며칠 전 동일한 문제가 발생했습니다. 내 문제와 해결책을 직접 볼 수 있습니다. 스프링 MVC 컨트롤러 예외 테스트

    내 대답이 너를 도우려는 걸 원해.

  4. ==============================

    4.Spring MockMVC를 사용하여 단위 테스트 스위트에서 요청 필터링 또는 예외 처리 테스트를 통합 할 수있는 지점까지 servletContainer를 에뮬레이트하십시오.

    Spring MockMVC를 사용하여 단위 테스트 스위트에서 요청 필터링 또는 예외 처리 테스트를 통합 할 수있는 지점까지 servletContainer를 에뮬레이트하십시오.

    다음 방법을 사용하여이 설정을 구성 할 수 있습니다.

    사용자 정의 RecordNotFound 예외가 발생했습니다 ...

    @ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Record not found") //
    public class RecordNotFoundException extends RuntimeException {
    
        private static final long serialVersionUID = 8857378116992711720L;
    
        public RecordNotFoundException() {
            super();
        }
    
        public RecordNotFoundException(String message) {
            super(message);
        }
    }
    

    ... 및 RecordNotFound 예외 핸들러

    @Slf4j
    @ControllerAdvice
    public class BusinessExceptionHandler {
    
        @ExceptionHandler(value = RecordNotFoundException.class)
        public ResponseEntity<String> handleRecordNotFoundException(
                RecordNotFoundException e,
                WebRequest request) {
             //Logs
            LogError logging = new LogError("RecordNotFoundException",
                    HttpStatus.NOT_FOUND, 
                    request.getDescription(true));
            log.info(logging.toJson());
    
            //Http error message
            HttpErrorResponse response = new HttpErrorResponse(logging.getStatus(), e.getMessage());
            return new ResponseEntity<>(response.toJson(),
                    HeaderFactory.getErrorHeaders(),
                    response.getStatus());
        }
       ...
    }
    

    맞춤형 테스트 컨텍스트 구성 : @ContextConfiguration을 설정하여 테스트에 필요한 클래스를 지정하십시오. Mockito MockMvc를 서블릿 컨테이너 에뮬레이터로 설정하고 테스트 픽스처와 의존성을 설정하십시오.

     @RunWith(SpringRunner.class)
    @ContextConfiguration(classes = {
        WebConfig.class,
        HeaderFactory.class,
    })
    @Slf4j
    public class OrganisationCtrlTest {
    
        private MockMvc mvc;
    
        private Organisation coorg;
    
        @MockBean
        private OrganisationSvc service;
    
        @InjectMocks
        private OrganisationCtrl controller = new OrganisationCtrl();
    
        //Constructor
        public OrganisationCtrlTest() {
        }
       ....
    

    모의 MVC "서블릿 에뮬레이터"를 설정합니다 : 컨텍스트에서 핸들러 빈을 등록하고 mockMvc 에뮬레이터를 빌드하십시오 (참고 : 두 가지 가능한 구성이 있습니다 : standaloneSetup 또는 webAppContextSetup, 문서 참조). 빌더는 빌더 패턴을 올바르게 구현하므로 build ()를 호출하기 전에 예외 확인 자 및 핸들러에 대한 구성 명령을 연결할 수 있습니다.

        @Before
        public void setUp() {
            final StaticApplicationContext appContext = new StaticApplicationContext();
            appContext.registerBeanDefinition("BusinessExceptionHandler",
                    new RootBeanDefinition(BusinessExceptionHandler.class, null, null));
    
    //InternalExceptionHandler extends ResponseEntityExceptionHandler to //handle Spring internally throwned exception
            appContext.registerBeanDefinition("InternalExceptionHandler",
                    new RootBeanDefinition(InternalExceptionHandler.class, null,
                            null));
            MockitoAnnotations.initMocks(this);
            mvc = MockMvcBuilders.standaloneSetup(controller)
                    .setHandlerExceptionResolvers(getExceptionResolver(appContext))
                    .build();
            coorg = OrganisationFixture.getFixture("orgID", "name", "webSiteUrl");
        }
        ....
    

    테스트를 실행하십시오.

        @Test
        public void testGetSingleOrganisationRecordAnd404() throws Exception {
            System.out.println("testGetSingleOrganisationRecordAndSuccess");
            String request = "/orgs/{id}";
            log.info("Request URL: " + request);
    
            when(service.getOrganisation(anyString())).
                    thenReturn(coorg);
            this.mvc.perform(get(request)
                    .accept("application/json")
                    .andExpect(content().contentType(
                            .APPLICATION_JSON))
                    .andExpect(status().notFound())
                    .andDo(print());
        }
        ....
    }
    

    희망이 도움이됩니다.

    제이크.

  5. ==============================

    5.이게 낫다:

    이게 낫다:

    ((HandlerExceptionResolverComposite) wac.getBean("handlerExceptionResolver")).getExceptionResolvers().get(0)
    

    그리고 @Configuration 클래스에서 @ControllerAdvice 빈을 스캔하는 것을 잊지 마십시오.

    @ComponentScan(basePackages = {"com.company.exception"})
    

    ... Spring 4.0.2에서 테스트되었습니다.

  6. ==============================

    6.시도 해봐;

    시도 해봐;

    @RunWith(value = SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @ContextConfiguration(classes = { MVCConfig.class, CoreConfig.class, 
            PopulaterConfiguration.class })
    public class ExceptionControllerTest {
    
        private MockMvc mockMvc;
    
        @Mock
        private StatusController statusController;
    
        @Autowired
        private WebApplicationContext wac;
    
        @Before
        public void setup() {
            this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
        }
    
        @Test
        public void checkUnexpectedExceptionsAreCaughtAndStatusCode500IsReturnedInResponse() throws Exception {
    
            when(statusController.checkHealth()).thenThrow(new RuntimeException("Unexpected Exception"));
    
            mockMvc.perform(get("/api/status"))
                    .andDo(print())
                    .andExpect(status().isInternalServerError())
                    .andExpect(jsonPath("$.error").value("Unexpected Exception"));
        }
    }
    
  7. from https://stackoverflow.com/questions/16669356/testing-spring-mvc-exceptionhandler-method-with-spring-mvc-test by cc-by-sa and MIT license