2016-07-09 4 views
1

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ückkehren

Basierend 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.

Antwort

0

Die Antwort, die Sie von Ihrem Ausnahmebehandler zurückgegeben haben, muss dem Header "Accept" der Anforderung entsprechen. Wenn nicht, erhalten Sie die beschriebene Ausnahme. Spring berücksichtigt auch einige Standardwerte, wenn der Header "Accept" nicht gesetzt ist.

Ich war vor ein paar Tagen mit einem ähnlichen Problem konfrontiert und versuchte, die Feder so zu konfigurieren, dass immer ein fester Inhaltstyp (z. B. application/json) für die Antwort verwendet wurde, aber es erwies sich als zu kompliziert.

einen Haltepunkt an der Linie 189 von

writeWithMessageConverters AbstractMessageConverterMethodProcessor # Set

Dort finden Sie requestedMediaTypes, producibleMediaTypes und compatibleMediaTypes sehen. Dies sollte Ihnen mehr Informationen darüber geben, was eigentlich der Grund des Problems ist.

bearbeiten

Es gibt keine allgemeine Lösung für dieses Problem. Sie müssen untersuchen, warum der Frühling zu dem Schluss kommt, dass es keinen akzeptablen Medientyp gibt. Der beste Rat, den ich geben kann, ist, die drei Variablen am oben beschriebenen Haltepunkt zu überprüfen.

  • requestedMediaTypes - die Medientypen der Anträge auf ‚Akzeptieren‘ Header oder einen Standard, wenn der Header nicht
  • producibleMediaTypes gesetzt wurde - die Medientypen, dass die Controller-Methode produzieren kann.
  • compatibleMediaTypes - die Medientypen der oben genannten, die Auffassung, dass Feder kompatibel

Wenn der compatibleMediaTypes nicht null oder leer ist, kann der Fehler passieren, wenn der Frühling versucht, Ihre ServiceError zu serialisiert. Also überprüfen Sie, ob Sie die richtigen Anmerkungen dort haben, Getter/Setter-ID benötigt ....

Wenn die compatibleMediaTypes Null sind, dann haben Sie wirklich inkompatible Medientypen und Sie müssen das ändern.

* Wie ich mein Problem gelöst *

Mein Controller diese Ausnahme ausgelöst hat, wenn ein Client einen Medientyp angefordert, die nur falsch geschrieben wurde oder nicht von meinem Controller unterstützt, und ich versuchte, einen JSON Fehlerantwort zurück. In dieser Situation macht es Sinn, KEINE JSON-Antwort zurückzugeben, da der Client sie sowieso nicht akzeptieren kann. Ich gebe also nur den HTTP-Status 400 (Bad Request) und überhaupt keinen Inhalt zurück.

+0

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? –

+0

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. –

Verwandte Themen