Java 8 представлен java.time.Clock
который может использоваться в качестве аргумента многим другой java.time
объекты, позволяя Вам ввести реальные или поддельные часы в них. Например, я знаю, что можно создать a Clock.fixed()
и затем звоните Instant.now(clock)
и это возвратит фиксированное Instant
Вы обеспечили. Это звучит идеально подходящим для поблочного тестирования!
Однако я испытываю затруднения при выяснении, как лучше всего использовать это. У меня есть класс, подобный следующему:
public class MyClass {
private Clock clock = Clock.systemUTC();
public void method1() {
Instant now = Instant.now(clock);
// Do something with 'now'
}
}
Теперь, я хочу к модульному тесту этот код. Я должен смочь установить clock
произвести зафиксированные времена так, чтобы я мог протестировать method()
в разное время. Очевидно, я мог использовать отражение для установки clock
участник к определенным значениям, но было бы хорошо, если бы я не должен был обращаться к отражению. Я мог создать общественность setClock()
метод, но это чувствует себя неправильным. Я не хочу добавлять a Clock
аргумент методу, потому что реальный код не должен касаться передачи в часах.
Каков лучший подход для обработки этого? Это - новый код, таким образом, я мог реорганизовать класс.
Править: Для разъяснения я должен смочь создать сингл MyClass
объект, но смочь иметь тот один объект видит два различных значения часов (как будто это были обычные системные часы, отсчитывающие вперед). По сути, я не могу передать фиксированные часы в конструктора.
Для запуска определенно введите Clock
в класс под тестом, как рекомендуется @Jon Стрельбой по тарелочкам. Если Ваш класс только требует одного времени, то просто передают в Clock.fixed(...)
значение. Однако, если Ваш класс ведет себя по-другому через время, например, он делает что-то во время A, и затем делает что-то еще во время B, затем отмечает, что часы, созданные Java, неизменны и таким образом не могут быть изменены тестом для возврата времени когда-то и затем времени B в другом.
Насмешка, согласно принятому ответу, является одной опцией, но действительно сильно связывает тест к реализации. Например, как один комментатор указывает, что если класс при проверочных вызовах LocalDateTime.now(clock)
или clock.millis()
вместо clock.instant()
?
альтернативный подход, который является немного более явным, легче понять, и может быть более устойчивым, чем насмешка, должен создать реальную реализацию Clock
, который является изменяем , так, чтобы тест мог ввести его и изменить его по мере необходимости. Это не трудно реализовать. См. https://github.com/robfletcher/test-clock для хорошего примера этого.
MutableClock c = new MutableClock(Instant.EPOCH, ZoneId.systemDefault());
ClassUnderTest classUnderTest = new ClassUnderTest(c);
classUnderTest.doSomething()
assertTrue(...)
c.instant(Instant.EPOCH.plusSeconds(60))
classUnderTest.doSomething()
assertTrue(...)