【问题标题】:Test ExceptionHandler with RestTemplate使用 RestTemplate 测试 ExceptionHandler
【发布时间】:2022-01-22 01:59:21
【问题描述】:

我有一个对外部 API 产生影响的方法,并且我编写了异常处理程序来处理错误并在发生错误时发送对客户端友好的响应。我需要测试来自该外部 API 的非 200 OK 响应,例如错误请求、内部服务器错误,并断言应该调用异常处理程序方法以发送对客户端友好的消息。我能够成功地将外部 API 的响应模拟为错误请求,但它没有抛出 HttpStatusCodeException 理想情况下抛出 4xx 状态代码以及如何验证异常处理程序的方法调用

  private final RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
  private final HttpHeaders httpHeaders = new HttpHeaders();
  private final NotificationServiceImpl notificationService = new NotificationServiceImpl(restTemplate, httpHeaders, NOTIFICATION_API_URL, PRIMARY_NOTIFIERS, CC_NOTIFIERS, LANG, APPLICATION_NAME);

  @Autowired
  private ExceptionTranslator exceptionTranslator;

  @Test
  void testErrorOnSendNotification() {
    Map<String, Instant> messages = Map.of("sample message", Instant.now());
    ResponseEntity<HttpStatusCodeException> responseEntity =
        new ResponseEntity<>(HttpStatus.BAD_REQUEST);

    when(restTemplate.exchange(
        ArgumentMatchers.anyString(),
        ArgumentMatchers.any(HttpMethod.class),
        ArgumentMatchers.any(),
        ArgumentMatchers.<Class<HttpStatusCodeException>>any()))
        .thenReturn(responseEntity);

//    assertThrows(HttpStatusCodeException.class, () -> notificationService.sendNotification(messages));
    verify(exceptionTranslator, times(1)).handleExceptions(any(), any());
  }

@ExceptionHandler(Exception.class)
  public ResponseEntity<Problem> handleExceptions(NativeWebRequest request, Exception error) {
    Problem problem =
        Problem.builder()
            .withStatus(Status.BAD_REQUEST)
            .withTitle(error.getMessage())
            .withDetail(ExceptionUtils.getRootCauseMessage(error))
            .build();
    return create(error, problem, request);
  }

【问题讨论】:

    标签: java spring spring-boot mockito resttemplate


    【解决方案1】:

    您在嘲笑 restTemplate 响应。实际的@ExceptionHandler 根本没有被调用。您正在绕过该层。

    在您的情况下,为了验证ExceptionHandler,可以模拟您的service 层,但必须继续执行实际的REST 调用,并且必须触发真正的response,以便为您服务验证响应Status Code + message

    下面的伪代码:

    @Service
    class Service{
     
        public void doSomeBusinessLogic() throws SomeException;
    }
      
      
    @RestController
    class ControllerUsingService{
    
      @AutoWired
      private Service service;
    
      @POST
      public Response somePostMethidUsingService() throws SomeException{
        
          service.doSomeBusinessLogic(someString);
      }
    }
    

      @Test
      void testErrorOnSendNotification() {
    
       when(service.doSomeBusinessLogic(anyString()))
      .thenThrow(SomeExceptionException.class);
    
    
        Response receivedResponse = restTemplate.post(request, headers, etc);
         
        //assert receivedResponse status code + message.
      }
    

    希望这是有道理的,

    进一步说明:

    通过做:

    ResponseEntity<HttpStatusCodeException> responseEntity =
            new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    
        when(restTemplate.exchange(
            ArgumentMatchers.anyString(),
            ArgumentMatchers.any(HttpMethod.class),
            ArgumentMatchers.any(),
            ArgumentMatchers.<Class<HttpStatusCodeException>>any()))
            .thenReturn(responseEntity);
    

    你绕过了服务层,实际上是说每当我向/API/xyz 发出请求时,我应该会收到BAD_REQUEST。这意味着您拥有的任何异常处理都将被绕过。

    【讨论】:

      猜你喜欢
      • 2016-08-01
      • 2013-01-14
      • 2013-05-16
      • 2016-01-29
      • 2015-10-22
      • 2020-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多