首页 文章

在Spring Controller的catch块中测试代码

提问于
浏览
1

我有以下结构的控制器:

@RequestMapping(value = "${foo.controller.requestMappingUrl.login}", method = RequestMethod.POST)
    public ResponseMessage<String> loginUser(
            @RequestParam("username") String username, HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse) {

    try {

       return fooService.login(username); // can mock test

    } catch (UserNotFoundException e) {
            //CANNOT MOCK TEST THIS BLOCK
            String errorMsg = LoggerUtil.printStackTrace(e);
            LOG.error("[RequestId: {}] UserNotFoundException: {}, Stack: {}", requestId, e.getMessage(), errorMsg);
            httpServletResponse.setStatus(HttpStatus.NOT_ACCEPTABLE.value());
            statusCode = StatusCode.UserNotFound.value();
            responseMessage.buildResponseMessage(StringUtils.EMPTY, HttpStatus.NOT_ACCEPTABLE, statusCode,
                    messageByLocaleService.getMessageResponse(statusCode, null, locale));
    }
}

当我模拟抛出异常UserNotFoundException时,我只得到NestedServletException . 即使我尝试添加expected = NestedServletException.class . corbetura报告表明代码块未包含在测试中 . 您是否有任何建议可以帮助测试catch块中的代码 .

要求的测试代码:

@SuppressWarnings("unchecked")
@Test(expected = UserNotFoundException.class)
    public void testControllerUserNotFoundException() throws Exception {
        Response resp = new Response();
        resp.setStatusCode(StatusCode.UserNotFoundErrorCode);
        when(fooService.login(any(String.class)).thenThrow(UserNotFoundException.class);

        mockMvc.perform(post("/service-user/1.0/auth/login?&username=test")
                        .contentType(contentType)).andExpect(status().isNotAcceptable())
                .andExpect(jsonPath("$.statusCode", is("ERRORCODE144")));

    }

和堆栈跟踪

java.lang.Exception:意外异常,但是在org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores)的org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)中 . .java:26)atg.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86 )org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)org.jun.runner.Runner.runLeaf(ParentRunner.java:325)org.springframework.test.context上的org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) . junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:290) )org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java: 71)org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:58)org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner) .java:268)org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70 )org.junit.runners.ParentRunner.run(ParentRunner.java:363)atg.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)org.eclipse.jdt.internal.junit4 . 在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner的org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)的runner.JUnit4TestReference.run(JUnit4TestReference.java:50) . runTests(RemoteTestRunner.java:467)org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)at org . eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)at or.e.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)引起:org.springframework . web.util.NestedServletException:请求处理失败;在org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)的嵌套异常是com.atlassian.crowd.exception.runtime.UserNotFoundException . 872)位于org.springframework.test.web.servlet.TestDispatcherServlet的org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)的javax.servlet.http.HttpServlet.service(HttpServlet.java:648) .service(TestDispatcherServlet.java:65)位于org.springframework.mock.web.MockFilterChain $ ServletFilterProxy.doFilter(MockFilterChain.java:167)的javax.servlet.http.HttpServlet.service(HttpServlet.java:729) . springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)位于org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155)的id.co.allianz.microservice.cop.app . sun.reflect.NativeMethod上的auth.controller.AuthControllerTest.testControllerUserNotFoundException(AuthControllerTest.java:105)在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)的sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)上的AccessorImpl.invoke0(本地方法),位于java.lang.reflect.Method.invoke(方法 . java:498)org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall(FrameworkMethod.java:50)org.junit上的org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) . 在org.junit.internal.runners.statements.ExpectException.evaluate的org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)中的runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) ExpectException.java:19)... 22更多引起:com.atlassian.crowd.exception.runtime.UserNotFoundException

1 回答

  • 4

    您不能指望控制器方法中出现 UserNotFoundException 异常,因为您通过简单地记录并使用 ERRORCODE144 返回响应来抑制它 .

    这里的最佳实践是配置 ControllerAdvice ,以便可以全局处理所有异常,并且控制器看起来很干净,如下所示,我建议您在 spring 控制器异常处理上查看here .

    ExceptionControllerAdvice class:

    @ControllerAdvice
    public class ExceptionControllerAdvice {
    
        @ExceptionHandler(UserNotFoundException.class)
        public ResponseEntity<String> handleUnexpectedException(UnexpectedException 
                         unExpectedExe) {
    
            //log and send the response back to the client here
        }
    }
    

    Controller method:

    @RequestMapping(value = "${foo.controller.requestMappingUrl.login}",
                                     method = RequestMethod.POST)
    public ResponseMessage<String> loginUser(
                @RequestParam("username") String username,
                   HttpServletRequest httpServletRequest,
                   HttpServletResponse httpServletResponse) {
    
           return fooService.login(username);
    }
    

    JUnit setup & test methods:

    @Before
        public void setUp() throws Exception {
            MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(projectController)
                    .setMessageConverters(new MappingJackson2HttpMessageConverter())
                    .setControllerAdvice(new ExceptionControllerAdvice()).build();
    }
    
    
    @SuppressWarnings("unchecked")
    @Test
        public void testControllerUserNotFoundException() throws Exception {
            Response resp = new Response();
            resp.setStatusCode(StatusCode.UserNotFoundErrorCode);
            when(fooService.login(any(String.class)).
            thenThrow(UserNotFoundException.class);
            mockMvc.perform(post("/service-user/1.0/auth/login?&username=test")
                            .contentType(contentType)).
         andExpect(status().isNotAcceptable())
                    .andExpect(jsonPath("$.statusCode", is("ERRORCODE144")));
    }
    

相关问题