2012-02-14 20 views
20

En mi código que tienen algo como esto:java: cómo burlarse de Calendar.getInstance()?

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

¿Cómo puedo "mock" en mi prueba junit para devolver una fecha específica?

+1

Esa línea no se pudo compilando! – adarshr

+0

¿Es 'today' un miembro de la clase (campo) o una variable local dentro de un método? –

+0

variable local dentro de un método – Randomize

Respuesta

14

Por lo que yo veo que usted tiene tres opciones de forma inteligente:

  1. inyectar el ejemplo Calendar en cualquier método/clase se establece ese día en.

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

  2. Utilice JodaTime en lugar de Calendar. Esto es menos una opción y más una sugerencia ya que JodaTime hará su vida mucho más fácil. Todavía necesitará inyectar este tiempo en el método.

    DateTime dt = new DateTime();

    Date jdkDate = dt.toDate();

  3. Wrap Calendar dentro de alguna de las interfaces que le permite buscar el tiempo. Entonces solo se burla de esa interfaz y la devuelve una constante Date.

    Date today = calendarInterfaceInstance.getCurrentDate()

+3

La clase 'DateTimeUtils' de Joda Time tiene métodos estáticos que establecen la hora actual para todos los demás objetos Joda Time. Esto es muy útil para establecer el tiempo en un determinado momento, por ejemplo, para la prueba. – Jesper

+0

@Jesper - Sí, eso es cierto y es un buen punto que olvidé mencionar – BeRecursive

+1

Gracias chicos. Seguí tus sugerencias y me mudé a JodaTime. Por cierto, corrige fácilmente el problema con algo como: DateTimeUtils.setCurrentMillisFixed (new DateTime (2012, 2, 14, 13, 43, 21) .getMillis()); – Randomize

9

No se burle, sino que presente un método que puede simular que obtiene las fechas. Algo como esto:

interface Utility { 

    Date getDate(); 
} 

Utilities implements Utility { 


    public Date getDate() { 

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

} 

A continuación, se puede inyectar esto en su clase o simplemente utilizar una clase de ayuda con un montón de métodos estáticos con un método de carga para la interfaz:

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

} 

Luego, en su solicitud código:

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

Puede cargar una interfaz de simulación en sus métodos de prueba.

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

    // .. set up your expectations 

    // exercise the functionality 
    classUnderTest.doSomethingViaAPI(); 

    // ... maybe assert something 

} 

Ver también Should you only mock types you own? y Test smell - everything is mocked

2

escribir una clase llamada DateHelper con un método que devuelve getCalendarCalendar.getInstance(). Refactorice la clase que está probando para que tenga una variable miembro del tipo DateHelper, y un constructor que inyecte esa variable miembro. Use ese constructor en su prueba para inyectar un simulacro de DateHelper, en el que getCalendar ha sido anulado para devolver alguna fecha conocida.

9

Puede burlarse usando PowerMock en combinación con Mockito:

En la parte superior de su clase:

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

La clave del éxito es que usted tiene que poner la clase en la que utiliza Calendario de PrepareForTest en lugar de Calendar en sí porque es una clase de sistema. (Yo personalmente tuve que buscar mucho antes de encontrar este)

A continuación, la burla en sí:

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

¿qué dependencias incluye para que funcione el método mockStatic()? –

+0

Lo siento, debería haber dicho eso. Utilicé importación estática para importar el método simulado de PowerMockito. Vea esta dependencia para powermock mockito: http://mvnrepository.com/artifact/org.powermock/powermock-api-mockito2/1.6.6 – GoGoris

6

Usando Mockito y PowerMockito:

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

Consulte la link para el código completo.

0

Para los que sigue el patrón MVP burlarse calendario es un pedazo de la torta:

  1. En un presentador crear un método que devuelve instancia calendario:

    public Calendar getCurrentTime() { 
         return Calendar.getInstance();  
        } 
    
  2. En su opinión (Actividad, Fragmento, etc.) accede al calendario con la ayuda del presentador:

    Calendar calendar = mPresenter.getCurrentTime(); 
    // do whatever you want 
    
  3. En sus pruebas lo hace:

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