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

时间:2019-08-08 13:18:25

标签: rest spring-boot junit java-8 mockito

@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方法

1 个答案:

答案 0 :(得分: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"))

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