2013-05-21 8 views
28

J'ai le contrôleur simple suivant pour intercepter toutes les exceptions inattendues:Méthode d'essai Spring MVC @ExceptionHandler avec Spring MVC test

@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); 
    } 
} 

Je suis en train d'écrire un test d'intégration en utilisant le framework de test Spring MVC. Voilà ce que j'ai jusqu'à présent:

@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")); 
    } 
} 

je me inscrire le ExceptionController et une StatusController maquette dans l'infrastructure Spring MVC. Dans la méthode de test, je définis une attente de lancement d'une exception à partir de StatusController.

L'exception est levée, mais ExceptionController ne la traite pas.

Je veux être en mesure de tester que ExceptionController obtient des exceptions et renvoie une réponse appropriée.

Des pensées sur pourquoi cela ne fonctionne pas et comment je devrais faire ce genre de test?

Merci.

+0

Je suppose que dans le test des gestionnaires d'exception ne sont pas assignés, ne sais pas pourquoi exactement mais c'est pourquoi cela arrive, regardez cette réponse http: // stackoverflow. com/questions/11649036/exceptionhandler-not-travail-avec-printemps-mvc-3-1-test-unité – engma

+0

Des nouvelles à ce sujet? Je suis dans la même situation. – Cemo

+0

Je n'ai pas trouvé de solution. J'ai décidé que je ferais confiance au travail @ExceptionHandler et puisque la méthode elle-même est simple, j'ai décidé que je pourrais vivre sans tester cette annotation. Vous pouvez toujours tester la méthode avec un test unitaire régulier. – C0deAttack

Répondre

0

Étant donné que vous utilisez un test d'installation autonome, vous devez fournir un gestionnaire d'exceptions manuellement.

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

J'ai eu même problème quelques jours en arrière, vous pouvez voir mon problème et la solution ont répondu par moi-même ici Spring MVC Controller Exception Test

Espérant que ma réponse vous aider

-1

Essayez-;

@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")); 
    } 
} 
3

Ce code ajoutera la possibilité d'utiliser vos conseils contrôlés par les exceptions.

@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; 
} 
30

Je viens d'avoir la même question et les travaux suivants pour moi:

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

Depuis le printemps 4.x.x ..... –

0

C'est mieux:

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

Et ne pas oublier de rechercher des haricots dans votre @ControllerAdvice @Configuration class:

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

... testé sur Spring 4.0.2.RELEASE