2012-02-14 15 views
20

W moim kodu mam coś takiego:java: jak wyśmiewać Calendar.getInstance()?

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

Jak mogę „mock” to w moim testu junit powrotu konkretną datę?

+1

Ta linia nie może być kompilacji! – adarshr

+0

Czy 'today' jest członkiem klasy (pole) lub zmienną lokalną wewnątrz metody? –

+0

zmienna lokalna wewnątrz metody – Randomize

Odpowiedz

14

O ile widzę to masz trzy sensowne opcje:

  1. wstrzyknąć Instancji w dowolnej metody/klasy ustawieniu tego dnia w Calendar.

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

  2. Użyj JodaTime zamiast Calendar. Jest to mniej opcja, a bardziej przypadek sugestii, ponieważ JodaTime ułatwi ci życie. Nadal będziesz musiał wprowadzić ten czas do metody.

    DateTime dt = new DateTime();

    Date jdkDate = dt.toDate();

  3. Wrap Calendar wewnątrz jakiegoś interfejsu, który pozwala pobierać czas. Po prostu kpisz z tego interfejsu i odzyskujesz stałą wartość: Date.

    Date today = calendarInterfaceInstance.getCurrentDate()

+3

Klasa 'DateTimeUtils' Joda Time ma statyczne metody, które ustawiają bieżący czas dla wszystkich innych obiektów Joda Time. Jest to bardzo przydatne, aby ustawić czas na określony moment, na przykład do testowania. – Jesper

+0

@Jesper - Tak, to prawda i dobrze, że zapomniałem wspomnieć o – BeRecursive

+1

Dziękuję. Posłuchałem sugestii i przeniosłem się do JodaTime. BTW to łatwo rozwiązuje problem z czymś takim jak: DateTimeUtils.setCurrentMillisFixed (new DateTime (2012, 2, 14, 13, 43, 21) .getMillis()); – Randomize

9

Nie kpij z niego - zamiast tego wprowadź metodę, którą możesz kpić, która dostaje daty. Coś takiego:

interface Utility { 

    Date getDate(); 
} 

Utilities implements Utility { 


    public Date getDate() { 

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

} 

Następnie można wstrzyknąć to w swojej klasie lub po prostu użyć klasy pomocnika z grupą metod statycznych z metodą obciążenia dla interfejsu:

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

} 

Następnie w aplikacji kod:

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

Następnie można załadować fałszywy interfejs w swoich metodach testowych.

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

    // .. set up your expectations 

    // exercise the functionality 
    classUnderTest.doSomethingViaAPI(); 

    // ... maybe assert something 

} 

Zobacz także Should you only mock types you own? i Test smell - everything is mocked

2

Napisz klasę o nazwie DateHelper z metodą getCalendar zwracającej Calendar.getInstance(). Zmodyfikuj klasę, którą testujesz, aby zawierała zmienną składową typu DateHelper, i konstruktor, który wstrzykuje tę zmienną składową. Użyj tego konstruktora w teście, aby wstrzyknąć próbkę o numerze DateHelper, w której getCalendar został zgrupowany, aby zwrócić znaną datę.

9

Można wyśmiewać go za pomocą PowerMock w połączeniu z Mockito:

Na szczycie swojej klasy:

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

Kluczem do sukcesu jest to, że trzeba umieścić klasę w której używasz kalendarz w PrepareForTest zamiast samego kalendarza, ponieważ jest to klasa systemowa. (Ja osobiście miałem szukać dużo wcześniej znalazłem to)

Następnie szydząc sobie:

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

które zależności zawierają dla uzyskania metody mockStatic() działają? –

+0

Przepraszam, powinienem był to powiedzieć. Użyłem importu statycznego do zaimportowania metody mockStatic PowerMockito. Zobacz tę zależność dla powermock mockito: http://mvnrepository.com/artifact/org.powermock/powermock-api-mockito2/1.6.6 – GoGoris

6

Korzystanie Mockito i PowerMockito:

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

Patrz link dla całego kodu.

0

Dla tych, którzy następująco MVP wzorzec szyderczy kalendarz jest bułka z masłem:

  1. W Presenter stworzyć metodę, która zwraca instancję kalendarza:

    public Calendar getCurrentTime() { 
         return Calendar.getInstance();  
        } 
    
  2. W widoku (aktywność, Fragment itp.) Można uzyskać dostęp do kalendarza za pomocą prezentera:

    Calendar calendar = mPresenter.getCurrentTime(); 
    // do whatever you want 
    
  3. w badaniach zrobić:

    // create a dummy calendar 
    Calendar mockCalendar = ... 
    // You've already mocked your Presenter, haven't you? 
    when(mMockPresenter.getCurrentTime()).thenReturn(mockCalendar); 
    // here you are! 
    
Powiązane problemy