如何使用 mockito 为以下异常处理程序方法编写单元测试?

Posted

技术标签:

【中文标题】如何使用 mockito 为以下异常处理程序方法编写单元测试?【英文标题】:How to write Unit Test for below Exception Handler method using mockito? 【发布时间】:2019-12-16 05:21:47 【问题描述】:
@ExceptionHandler( ConstraintViolationException.class )
public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex, WebRequest request) 
    StringBuilder messageBuilder = new StringBuilder("Validation failed for: ");
    ex.getConstraintViolations()
        .stream()
        .forEach(v -> messageBuilder
            .append("property: [" + v.getPropertyPath() + "], value: [" + v.getInvalidValue() + "], constraint: [" + v.getMessage() + "]"));
    return new ResponseEntity<>(responseBuilder
        .createErrorResponse(INVALID_PARAMETER,
            messageBuilder.toString()), getHeaders(), BAD_REQUEST);

我想测试这个@ControllerAdvice 方法

【问题讨论】:

你只是想测试这个方法还是想测试这个 ExceptionHandler 是否按预期使用? 只是想测试这个异常处理程序是否按预期工作 【参考方案1】:

如果您只想测试该方法,只需创建ConstraintViolationException 的实例(您的输入)并检查应用于它的handleConstraintViolation 方法的输出即可。 你可以这样做:

ContraintViolationException exception = mock(ContraintViolationException.class);
WebRequest webRequest = mock(WebRequest.class); 
YourControllerAdvice controllerAdvice = new YourControllerAdvice();
Set<ConstraintViolation<?>> violations = new HashSet<>();
ConstraintViolation mockedViolation = mock(ConstraintViolation.class);
given(mockedViolation.getPropertyPath()).willReturn("something");
// mock answer to other properties of mockedViolations 
...
violations.add(mockedViolation);  
given(exception.getContraintViolations()).willReturn(violations);

ResponseEntity<Object> response = controllerAdvice.handleContraintViolation(exception, webRequest);

assertThat(response.getStatusCode(), is(HttpStatus.BAD_REQUEST));

加上响应正文上的其他断言。 然而,很难知道 spring 抛出的所有不同的 ConstraintViolationException 实例可能是什么样子。

我建议您查看 MockMvc,它是 spring-boot-starter-test 的一部分。通过这种方式,您可以测试异常处理程序是否按预期使用,并且您可以验证 ResponseEntity 是否违反约束。

@WebMvcTest(YourController.class)
public class YourControllerMvcTest 

  @Autowired
  private MockMvc mvc;

  @Test
  public void constraintViolationReturnsBadRequest() throws Exception 
    // Instantiate the DTO that YourController takes in the POST request
    // with an appropriate contraint violation
    InputDto invalidInputDto = new InputDto("bad data");
    MvcResult result = mvc.perform(post("/yourcontrollerurl")
            .content(invalidInputDto)
            .contentType(MediaType.APPLICATION_JSON)
            .accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isBadRequest());

    // assert that the error message is as expected
    assertThat(result.getResponse().getContentAsString(), containsString("default message [must match"));
   

MockMvc 也有很好的 json 支持,因此可以添加:

.andExpect(MockMvcResultMatchers.jsonPath("$.field").value("expected value"))

而不是将响应验证为字符串。

【讨论】:

感谢您的努力,但我正在使用 Mockito 框架来测试此方法 查看更新后的答案。我仍然推荐 MockMvc,因为它与 Spring Boot 捆绑在一起。那么你就不需要 mockito 来进行这些测试了。

以上是关于如何使用 mockito 为以下异常处理程序方法编写单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

Mockito & Junit 空指针异常:名称不能为空

使用 Mockito 从模拟中抛出已检查的异常

模拟无效方法的try catch块并使用EasyMock或Mockito捕获异常

Mockito 测试 void 方法抛出异常

使用 mockito doThrow 测试 catch 块会立即执行

使用 mockito 测试周围的 try catch 方法