2012-02-14 3 views
20

В моем коде у меня есть что-то вроде этого:java: как насмехаться Calendar.getInstance()?

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

Как я могу «фиктивный» это в моем JUnit тест, чтобы вернуть конкретную дату?

+1

Эта линия не может быть компиляции! – adarshr

+0

Является ли 'today' членом класса (поля) или локальной переменной внутри метода? –

+0

Локальная переменная внутри метода – Randomize

ответ

14

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

  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()

+3

Класс 'DateTimeUtils' класса Joda Time имеет статические методы, которые устанавливают текущее время для всех других объектов времени Joda. Это очень полезно, чтобы установить время на определенный момент, например, для тестирования. – Jesper

+0

@ Jesper - Да, это правда и хорошая мысль, которую я пренебрег упоминать. – BeRecursive

+1

Спасибо, ребята. Я последовал советам ура, и я перешел в JodaTime. Кстати, он легко устраняет проблему с чем-то вроде: DateTimeUtils.setCurrentMillisFixed (новый DateTime (2012, 2, 14, 13, 43, 21) .getMillis()); – Randomize

9

Не издевайтесь над этим - вместо этого введите метод, который вы можете издеваться над датами. Что-то вроде этого:

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 

} 

Смотрите также Should you only mock types you own? и Test smell - everything is mocked

2

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

9

Вы можете дразнить его с помощью PowerMock в сочетании с Mockito:

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

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

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

Тогда насмешливый себя:

mockStatic(Calendar.class); 
when(Calendar.getInstance()).thenReturn(calendar); 
+0

Какие зависимости вы включаете для получения метода mockStatic()? –

+0

Извините, мне следовало это сказать. Я использовал import static для импорта mockStatic-метода PowerMockito. См. Эту зависимость для powermock mockito: http://mvnrepository.com/artifact/org.powermock/powermock-api-mockito2/1.6.6 – GoGoris

6

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

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

Обратитесь к link для полного кода.

0

Для тех, кто следует MVP шаблон издевательский календарь кусок пирога:

  1. В Presenter создать метод, который возвращает календарное экземпляр:

    public Calendar getCurrentTime() { 
         return Calendar.getInstance();  
        } 
    
  2. По вашему мнению (активность, Фрагмент и т. Д.), Вы получаете доступ к календарю с помощью ведущего:

    Calendar calendar = mPresenter.getCurrentTime(); 
    // do whatever you want 
    
  3. В своих тестах вы:

    // create a dummy calendar 
    Calendar mockCalendar = ... 
    // You've already mocked your Presenter, haven't you? 
    when(mMockPresenter.getCurrentTime()).thenReturn(mockCalendar); 
    // here you are! 
    
Смежные вопросы