ScalaTest: обрабатывать Instants как равные в течение одной миллисекунды
У меня есть класс case, который я сериализую в JSON, и тестовый пример, который проверяет, работает ли циклическое переключение.
Глубоко внутри корпуса класса находятся java.time.Instant
с, которые я положил в JSON как их эпоху миллисекунд.
Оказывается, что Instant
на самом деле имеет наносекундную точность, и это теряется при переводе, что делает тест неудачным, потому что временные метки немного сбиты.
Есть ли простой способ заставить Scalatest игнорировать разницу? Я просто хочу исправить тест, потеря точности полностью приемлема для приложения.
2 ответа
Мы используем Clock.instant, чтобы узнать текущее время вместо Instant.now, чтобы избежать этой проблемы. Таким образом, код для класса должен быть таким
class MyClass(clock: Clock) {
def getResult(): Result = {
Result(clock.instant)
}
}
и на тесте мы высмеиваем clock.instant, чтобы гарантировать, что мы проверяем в одно и то же время.
class MyClassTest {
val customTime = Instant.now
val clock = mock[Clock]
clock.instant() returns customTime
// test
val myClass = new MyClass(clock)
val expectedResult = Result(customTime)
myClass.getResult ==== expectedResult
}
Обрезать до миллисекунды перед сравнением
Я не уверен, что это поможет в вашей ситуации, но на всякий случай и для любого другого читающего вместе: правильный способ сравнения двух Instant
объекты, учитывающие только миллисекунды и более грубые, должны усекать каждый с точностью до миллисекунды (здесь, в Java):
Instant instant1 = Instant.parse("2018-12-14T08:25:54.232235133Z");
Instant instant2 = Instant.parse("2018-12-14T08:25:54.232975217Z");
if (instant1.truncatedTo(ChronoUnit.MILLIS).equals(instant2.truncatedTo(ChronoUnit.MILLIS))) {
System.out.println("Equal to the millisecond");
} else {
System.out.println("Not equal to the millisecond");
}
Выход:
Равно миллисекунде
Если вы точно знаете, что один из них уже был усечен в обратном направлении через JSON (и вы считаете это обязательным требованием), вам, конечно, не нужно усекать его снова.
Используйте часы, которые имеют только миллисекунду
Используя Clock
для тестирования часто хорошая идея. Это может помочь вам написать воспроизводимые тесты. Вы можете легко иметь часы, которые считают только миллисекунды:
Clock c = Clock.tickMillis(ZoneOffset.UTC);
System.out.println(c.instant());
System.out.println(Instant.now(c));
Вывод при запуске только сейчас:
2018-12-14T10:48:47.929Z 2018-12-14T10:48:47.945Z
Как видите, сгенерированный Instant
объекты имеют только три десятичных знака в секундах, то есть с точностью до миллисекунды и ничего более точного. Когда вы используете только Clock
для рисования Instant
s, не имеет значения, в какой часовой пояс вы переходите tickMillis
,