В моем коде у меня есть что-то вроде этого:
private void doSomething() {
Calendar today = Calendar.getInstance();
....
}
Как я могу "высмеять" его в своем тесте junit, чтобы вернуть конкретную дату?
В моем коде у меня есть что-то вроде этого:
private void doSomething() {
Calendar today = Calendar.getInstance();
....
}
Как я могу "высмеять" его в своем тесте junit, чтобы вернуть конкретную дату?
Насколько я понимаю, у вас есть три разумных варианта:
Внесите экземпляр Calendar
в любой метод/класс, который вы установили в этот день.
private void method(final Calendar cal)
{
Date today = cal.getTime();
}
Используйте JodaTime вместо Calendar
. Это меньше вариант и еще один пример предложения, поскольку JodaTime сделает вашу жизнь намного проще. Вам все равно придется вводить это время в метод.
DateTime dt = new DateTime();
Date jdkDate = dt.toDate();
Оберните Calendar
внутри некоторого интерфейса, который позволяет вам получить время. Затем вы просто издеваетесь над этим интерфейсом и возвращаете константу Date
.
Date today = calendarInterfaceInstance.getCurrentDate()
Не издевайтесь над этим - вместо этого введите метод, который вы можете издеваться над датами. Что-то вроде этого:
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
}
См. также Если вы только издеваетесь над типами, которыми владеете? и Проверить запах - все издевается
Вы можете издеваться над ним с помощью PowerMock в сочетании с Mockito:
В верхней части вашего класса:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassThatCallsTheCalendar.class})
Ключом к успеху является то, что вы должны поместить класс, в котором вы используете Calendar в PrepareForTest, вместо самого Календаря, потому что это системный класс. (Мне лично пришлось много искать, прежде чем я нашел это)
Затем насмехается:
mockStatic(Calendar.class);
when(Calendar.getInstance()).thenReturn(calendar);
Использование Mockito и PowerMockito:
Calendar endOfMarch = Calendar.getInstance();
endOfMarch.set(2011, Calendar.MARCH, 27);
PowerMockito.mockStatic(Calendar.class);
Mockito.when(Calendar.getInstance()).thenReturn(endOfMarch);
Обратитесь к ссылке для полного кода.
Напишите класс под названием DateHelper
с помощью метода getCalendar
, который возвращает Calendar.getInstance()
. Рефакторируйте класс, который вы тестируете, чтобы он имел переменную-член типа DateHelper
и конструктор, который вводит эту переменную-член. Используйте этот конструктор в своем тесте, чтобы ввести макет DateHelper
, в котором getCalendar
был заглушен, чтобы вернуть известную дату.
Вы можете издеваться, используя JMockit. Здесь вы можете увидеть, как вы можете это сделать: Mock Java Calendar - JMockit vs Mockito.
Для тех, кто следует шаблону MVP, насмешливый календарь - это кусок торта:
В презентаторе создайте метод, который возвращает экземпляр календаря:
public Calendar getCurrentTime() {
return Calendar.getInstance();
}
В вашем представлении (Activity, Fragment и т.д.) вы получаете доступ к календарю с помощью ведущего:
Calendar calendar = mPresenter.getCurrentTime();
// do whatever you want
В ваших тестах вы делаете:
// create a dummy calendar
Calendar mockCalendar = ...
// You've already mocked your Presenter, haven't you?
when(mMockPresenter.getCurrentTime()).thenReturn(mockCalendar);
// here you are!