Весенняя загрузка: Тестирование ответа, содержащего время Java

#java #json #spring-boot #unit-testing #mocking

#Ява #json #пружинный ботинок #модульное тестирование #осмеяние

Вопрос:

Мне нужно протестировать тело ответа Rest API, содержащее java.time.Instant поле. К сожалению, тест не может быть пройден из-за разницы в миллисекундах между фактическими и ожидаемыми отметками времени. Мне просто интересно, как я могу имитировать системные часы или как-то настроить контекст теста, чтобы тест прошел:

Класс тела ответа:

 public class ApiError {  private HttpStatus httpStatus;  private Instant timestamp;  private Listlt;ErrorDetailgt; errorDetails;   public ApiError(HttpStatus httpStatus) {  this.httpStatus = httpStatus;  this.timestamp = Instant.now();  }  // the rest of class is omitted for brevity }  

Тестовый класс:

 @WebMvcTest(controllers = UserController.class) class UserControllerTest {   @Autowired MockMvc mockMvc;  @Autowired ObjectMapper mapper;  ApiError apiError;   @Test  public void givenBlankField_WhenRequestIsReceived_ThenApiErrorGenerated() throws Exception {  SignUpRequest request = new SignUpRequest()  .setFirstName(" ") //validation error occurs  .setLastName("Doe")  .setPassword("123")  .setConfirmPassword("123")  .setEmail("john.doe@something.com")  .setConfirmEmail("john.doe@something.com");   MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/api/users/signup")  .content(mapper.writeValueAsString(request))  .contentType(MediaType.APPLICATION_JSON))  .andExpect(MockMvcResultMatchers.status().isBadRequest()).andReturn();   String actualResponseBody = result.getResponse().getContentAsString();   // Excpected response body:  apiError = new ApiError(HttpStatus.BAD_REQUEST);  FieldValidationErrorDetail errorDetail = new FieldValidationErrorDetail.Detail()  .field("firstName").message("{NotBlank.firstName}").rejectedValue(" ").build();  apiError.setErrorDetails(List.of(errorDetail));  String expectedResponseBody = mapper.writeValueAsString(apiError);   assertEquals(expectedResponseBody, actualResponseBody); //fails due to milliseconds difference between actual timestamp and expected timestamp  } }  

Ответ №1:

Объяснение

Здесь вы создаете экземпляр timestamp поля в два разных времени и сравниваете их. Они всегда будут не совпадать.

Решение

Я бы рекомендовал избегать создания экземпляра new ApiError(HttpStatus.BAD_REQUEST) в вашем тесте и просто проверять каждое поле по отдельности. Для timestamp поля просто убедитесь, что оно имеет ненулевое значение, или, если вы хотите быть педантичным, убедитесь, что оно имеет значение в течение последнего X секунд вместо точной проверки в миллисекундах, которую вы сейчас проверяете.

Альтернативное Решение (Хитрый Обходной Путь)

Если вы хотите продолжить проверку строки JSON на соответствие строке JSON, просто преобразуйте тело ответа в объект и украдите его метку времени в свой объект сравнения.

Комментарии:

1. Спасибо вам за ваш ответ! На самом деле я ищу способ поиздеваться над системными часами. Я нашел в Интернете несколько методов переопределения часов, но не смог успешно применить их к своему тестовому случаю. У вас есть какие-нибудь другие идеи?