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