ScalaTest: обрабатывать Instants как равные в течение одной миллисекунды - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть класс case, который я сериализирую в JSON, и тестовый пример, который проверяет, работает ли циклическое переключение.

Глубоко внутри класса case находятся java.time.Instant s, которые я помещаю в JSON каких эпоха, миллисекунды.

Оказывается, что Instant на самом деле имеет наносекундную точность , и это теряется при переводе, что делает тест неудачным, поскольку временные метки теперь немного смещены.

Есть ли простой способ заставить Scalatest игнорировать разницу?Я просто хочу исправить тест, потеря точности полностью приемлема для приложения.

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Обрезать до миллисекунды перед сравнением

Я не уверен, что это поможет в вашей ситуации, но в случае и для всех, кто читает дальше: правильный способ сравнения двух 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 с, не имеет значения, какой часовой пояс вы передаете tickMillis.

0 голосов
/ 13 декабря 2018

Мы используем 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
}
...