2017-01-10 2 views
1

Я выполняю единичный тест, который вызывает класс и проверяет, что метод в этом классе был вызван с определенными параметрами. Один из этих параметров - LocalDateTime.now().Mockito. Захват вызова LocalDateTime.now();

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

Это метод, который я смотрю на:

ServiceStatus serviceStatus = ServiceStatus.createNew(LocalDateTime.now()); 

Тест JUnit является:

verify(service).saveNotice(LocalDateTime.now)); 

Я попытался с помощью TimeFactory установить дату:

given(timeFactory.currentDateTime()).willReturn(NOW); 

, а затем:

given(message.getHeader("MESSAGE_CREATED_TIME")).willReturn(NOW.toString()); 

&

verify(service).saveNotice(NOW)); 

Но никакой радости.

Любые предложения?

(PS. В реальном коде есть и другие параметры, но я раздели их для простоты и по соображениям коммерческой тайны.)

+0

Я заметил, что вы не приняли ответ. Пожалуйста, подумайте об этом - если вам нужна дополнительная информация, не стесняйтесь оставить мне комментарий. – GhostCat

ответ

1

Мое предложение для Вас, чтобы использовать PowerMockito. Таким образом вы можете вернуть то, что вы хотите от звонка, до LocalDateTime.now().

Для этого вам нужно более или менее следующее (пример с Calendar класс):

 import org.powermock.api.mockito.PowerMockito; 
     import org.powermock.core.classloader.annotations.PrepareForTest; 
     import org.powermock.modules.junit4.PowerMockRunner; 
    // ... 

     @RunWith(PowerMockRunner.class) 
     @PrepareForTest({Calendar.class}) 
     public class DateUtilsTest { 

    public void testWithKnownCalendar(){ 
      PowerMockito.mockStatic(Calendar.class); 
      PowerMockito.when(Calendar.getInstance(TimeZone.getTimeZone("UTC"))).thenReturn(CalendarObjectFactory.getInstance().buildKnownCalendar(45)); 

     // your normal code here 
    } 
     } 

Адаптировать его с помощью LocalDateTime вместо Календарь.

4

Предлагаю не использовать PowerMock.

Ваша проблема заключается в том, что Статический звонок в now(). Это может выглядеть немного избыточно, но серьезно рассмотреть вопрос просто поставить некоторый небольшой интерфейс/класс вокруг этого статического вызова, например:

interface TimeStampProvider { 
    LocalDateTime getNow(); 
} 

«осущий» для этого можно просто вызвать LocalDateTime.now().

Но дело в том, что теперь вы просто передаете объект TimeStampProvider вашему классу (который вы можете прекрасно высмеять без необходимости PowerMock).

Вы видите: Powermock может привести к различным видам интересных причудливых проблем в долгосрочной перспективе; и особенно при написании вашего собственного кода: просто положите лучший дизайн; вместо того, чтобы пытаться «исправить» (частично) сломанный дизайн с помощью PowerMock.

+0

+1 для того, чтобы не использовать PowerMock и вместо этого использовать небольшой интерфейс. Это стандартное решение, оно даже встроено: см. [Часы] (https://docs.oracle.com/javase/8/docs/api/java/time/Clock.html). –

6

Не используйте PowerMock. Вместо этого используйте/mock a Clock. Переведите свой вызов на LocalDateTime.now() на номер LocalDateTime.now(clock). Из часов:

Лучшая практика для приложений - передавать часы в любой метод, требующий текущего момента. Рамки инъекции зависимостей являются одним из способов для достижения этой цели:

public class MyBean { 
    private Clock clock; // dependency inject 
    ... 
    public void process(LocalDate eventDate) { 
    if (eventDate.isBefore(LocalDate.now(clock)) { 
     ... 
    } 
    } 
} 

Такого подход позволяет альтернативные часы, такие как фиксированные или смещения, которые будут использоваться во время тестирования.

Одна стратегии есть, чтобы сделать clock окончательным, и предлагает два конструктора - один, который использует поставляемые часы, и один, который получает системные часы из Clock.systemDefaultZone() или Clock.systemUTC(). Другой способ - установить поле «Часы», которое можно настроить для тестирования, возможно, оставив его закрытым для пакета. В любом случае вы можете легко переопределить значение, предоставив Clock, созданный Clock.fixed(...), или напишите свою собственную реализацию, если вам нужно ее изменить в течение всего теста.

+0

Спасибо, Джефф! Я использовал это в своем коде сегодня. –

Смежные вопросы