Java: как издеваться над Calendar.getInstance ()? - PullRequest
26 голосов
/ 14 февраля 2012

В моем коде у меня есть что-то вроде этого:

private void doSomething() {
   Calendar today = Calendar.getInstance();
   ....
}

Как я могу "высмеять" его в моем тесте junit, чтобы вернуть определенную дату?

Ответы [ 6 ]

20 голосов
/ 07 апреля 2016

Вы можете смоделировать его, используя PowerMock в сочетании с Mockito:

На вершине вашего класса:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassThatCallsTheCalendar.class})

Ключ к успеху заключается в том, что вы должны поместить класс, в котором вы используете Calendar, в PrepareForTest вместо самого Calendar, поскольку это системный класс. (Лично мне пришлось много искать, прежде чем я нашел это)

Тогда само издевательство:

mockStatic(Calendar.class);
when(Calendar.getInstance()).thenReturn(calendar);
17 голосов
/ 14 февраля 2012

Насколько я понимаю, у вас есть три разумных варианта:

  1. Внедрить экземпляр Calendar в любой метод / класс, который вы установили в этот день.

    private void method(final Calendar cal) { Date today = cal.getTime(); }

  2. Используйте JodaTime вместо Calendar. Это не вариант, а скорее предложение, поскольку JodaTime сделает вашу жизнь намного проще. Вам все еще нужно будет ввести это время в метод.

    DateTime dt = new DateTime();

    Date jdkDate = dt.toDate();

  3. Wrap Calendar внутри некоторого интерфейса, который позволяет вам выбирать время. Затем вы просто издеваетесь над этим интерфейсом и заставляете его возвращать постоянную Date.

    Date today = calendarInterfaceInstance.getCurrentDate()

9 голосов
/ 14 февраля 2012

Не смейтесь - вместо этого представьте метод, который вы можете смоделировать, который получает даты Примерно так:

interface Utility {

    Date getDate();
}

Utilities implements Utility {


    public Date getDate() {

        return Calendar.getInstance().getTime();
    }

}

Затем вы можете добавить это в свой класс или просто использовать вспомогательный класс с набором статических методов с методом загрузки для интерфейса:

public class AppUtil {

    private static Utility util = new Utilities();

    public static void load(Utility newUtil) {

         this.util = newUtil;
    }

    public static Date getDate() {

        return util.getDate();
    }

}

Тогда в вашем коде приложения:

private void doSomething() {
   Date today = AppUtil.getDate();
   ....
}

Затем вы можете просто загрузить макет интерфейса в ваших методах тестирования.

@Test
public void shouldDoSomethingUseful() {
     Utility mockUtility = // .. create mock here
     AppUtil.load(mockUtility);

     // .. set up your expectations

     // exercise the functionality
     classUnderTest.doSomethingViaAPI();

     // ... maybe assert something 

}

См. Также Должны ли вы только издеваться над типами, которыми вы владеете? и Тестировать запах - все высмеивается

6 голосов
/ 14 апреля 2016

Использование Mockito и PowerMockito:

Calendar endOfMarch = Calendar.getInstance();
endOfMarch.set(2011, Calendar.MARCH, 27);
PowerMockito.mockStatic(Calendar.class);
Mockito.when(Calendar.getInstance()).thenReturn(endOfMarch);

Полный код см. По ссылке .

2 голосов
/ 14 февраля 2012

Напишите класс с именем DateHelper с методом getCalendar, который возвращает Calendar.getInstance(). Рефакторинг класса, который вы тестируете, чтобы он имел переменную-член типа DateHelper и конструктор, который внедряет эту переменную-член. Используйте этот конструктор в своем тесте, чтобы ввести макет DateHelper, в котором getCalendar был заглушен, чтобы вернуть некоторую известную дату.

1 голос
/ 04 сентября 2012

Вы можете смоделировать, используя JMockit.Вот как вы можете это сделать: Mock Java Calendar - JMockit против Mockito .

...