我有具有以下结构的控制器:
@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报告表明测试中未涵盖代码块。您是否有任何建议来帮助测试捕获块中的代码。
根据要求测试代码:
@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.statement.ExpectException.evaluate(ExpectException.java:28) 在 org.junit.internal.runners.statement.RunBefores.evaluate(RunBefores.java:26) 在 org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) 在 org.springframework.test.context.junit4.statement.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) 在 org.springframework.test.context.junit4.statement.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 在 org.springframework.test.context.junit4.statement.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) 在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 在 org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 原因:org.springframework.web.util.NestedServletException: 请求处理失败;嵌套异常是 com.atlassian.crowd.exception.runtime.UserNotFoundException at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982) 在 org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 在 org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65) at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167) 在 org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134) 在 org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155) 在 id.co.allianz.microservice.cop.app.auth.controller.AuthControllerTest.testControllerUserNotFoundException(AuthControllerTest.java:105) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在 org.junit.internal.runners.statement.ExpectException.evaluate(ExpectException.java:19) ...22 更多 原因: com.atlassian.crowd.exception.runtime.UserNotFoundException
您不能期望控制器方法出现UserNotFoundException
异常,因为您只是通过简单地记录并使用ERRORCODE144
返回响应来抑制它。
这里的最佳实践是配置ControllerAdvice
以便可以全局处理所有异常,并且您的控制器看起来很干净,如下所示,我建议您也查看 Spring 控制器异常处理。
异常控制器建议类:
@ControllerAdvice
public class ExceptionControllerAdvice {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<String> handleUnexpectedException(UnexpectedException
unExpectedExe) {
//log and send the response back to the client here
}
}
控制器方法:
@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 设置和测试方法:
@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")));
}