Ich verwende Mockito, um Spring Exception Handler zu testen. HierSpring @ExceptionHandler-Test wird aufgerufen, aber anstelle von error body wird die Exception mit Mockito erneut ausgegeben
ist der Test-Code:
@RunWith(MockitoJUnitRunner.class)
public class RestControllerTest {
@Mock
private InputValidationService inputValidationService;
@InjectMocks
private RestController controller;
private MockMvc mockMvc;
private List<String> errors;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(controller)
.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(RestControllerAdvice.class).resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(new RestControllerAdvice(), method);
}
return super.getExceptionHandlerMethod(handlerMethod, exception);
}
};
exceptionResolver.afterPropertiesSet();
return exceptionResolver;
}
@Test
public void thatExceptionHappens() throws Exception {
Set<ConstraintViolation<?>> violations = new HashSet<>();
doThrow(new ConstraintViolationException(violations)).when(inputValidationService).validateInput(anyString());
when(errorHelper.getErrorCode(anyString())).thenReturn("1000");
try {
mockMvc.perform(get("/employee/details/9876")).andDo(print()).andExpect(status().is(400));
} catch (Exception e) {
System.out.print("");
}
}
}
Hier ist der Controller-Code:
@ControllerAdvice
public class RestControllerAdvice {
@Resource
private ErrorHandler errorHandler;
@ExceptionHandler(value = { ConstraintViolationException.class })
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
public ServiceError handleConstraintViolations(ConstraintViolationException e) {
Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
return errorHandler.buildResponseFromViolations(violations);
}
}
Wenn ich den Test-Code ausführen, wirft es die Ausnahme, und die Ausführung geht zu ControllerAdvice dh RestControllerAdvice (Wie erwartet)
(Ich überprüfte das mit Debugger)
Jetzt ist hier die Ausgabe:
der Ausnahmebehandler dh handleConstraintViolations() komponiert die ErrorBody richtig, aber wenn die Ausführung auf den Prüfstand kommt wieder seine tatsächlich eine Ausnahme statt eines ErrorBody
Hier ist der Stack-Trace, die vielleicht geben Sie die Idee von was passiert.
Failed to invoke @ExceptionHandler method: public ErrorBody RestControllerAdvice.handleConstraintViolations(javax.validation.ConstraintViolationException)
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:251)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:153)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:165)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:363)
at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:60)
at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:137)
at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:74)
at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1185)
at org.springframework.test.web.servlet.TestDispatcherServlet.processHandlerException(TestDispatcherServlet.java:109)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1022)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:973)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:62)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:170)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:137)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:141)
at RestControllerTest.thatExceptionHappens(RestControllerTest.java:90)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
Could not complete request
javax.validation.ConstraintViolationException
at RestController.validateInput(RestController.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:961)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:62)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:170)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:137)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:141)
at RestControllerTest.thatExceptionHappens(RestControllerTest.java:90)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
Also im Grunde, wenn die folgende Zeile Code ausführt:
mockMvc.perform(get("/employee/details/9876")).andDo(print()).andExpect(status().is(400));
diese besondere Linie sollte nicht eine Ausnahme, die Ausnahme und alle sollten sich um ControllerAdvice genommen werden, und es sollte die ErrorBody
zurückkehrenBasierend auf der Antwort unten, hier einige zusätzliche Informationen, die ich gefunden:
requestMediaTypes has the following "*/*"
supportedMediaTypes has the following
application/octet-stream
text/plain/;charset=ISO-8859
application/xml
text/xml
application/x-form-urlencoded
multipart/form-date
*/*
producibleMediaTypes has the following
application/json;charset=UTF-8
compatibleMediaTypes has the following:
application/json;charset=UTF-8
assoziierten
Liste der Nachricht Converters:
0 = {[email protected]}
1 = {[email protected]}
2 = {[email protected]}
3 = {[email protected]}
Jetzt kann ich dieses Problem sehen passiert, wenn messageConverter1.canWrite (returnValueClass, selectedMediaType) wird ausgeführt und keiner von ihnen sind in der Lage Ich denke, zu konvertieren.
Auch wenn ich dem Thema näher gekommen bin, bin ich immer noch ratlos, wie ich das Problem lösen kann. Gibt es etwas, das ich in der setUp-Methode meiner Testklasse hinzufügen muss.
Ich bin froh, dass Sie Ihr Problem gelöst haben. Aber wie genau haben Sie das Problem gelöst? Weil der Error-Body (Meine Antwort) auch im JSON-Format zurückgegeben werden soll. Also was soll ich hier genau machen? –
Basierend auf Ihrer Antwort, die ziemlich gut ist, muss ich sagen. Ich habe den wahren Punkt der Ausnahme, die ich wieder geworfen habe, eingegrenzt, aber ich weiß immer noch nicht, wie ich das beheben soll. Ich habe einen Nachrichtenkonverter in meinem Setup hinzugefügt, der nicht einmal in der Liste der Nachrichtenkonverter angezeigt wird. –