2010-12-15 18 views
20

Quiero probar este método:¿Cómo puedo simular la fecha real de JodaTime?

public FirmOrder findActiveByModelColor(ModelColor modelColor) { 
    Query query = em.createQuery("FROM FirmOrder fo WHERE fo.modelColor = :modelColor AND fo.year = :year AND fo.month = :month"); 
    query.setParameter("modelColor", modelColor); 
    query.setParameter("year", new DateTime().year().get()); 
    query.setParameter("month", new DateTime().monthOfYear().get()); 
    return (FirmOrder) query.getSingleResult(); 
} 

pero necesito DateTime().year().get() y DateTime().dayOfMonth().get() para volver siempre la misma fecha

TKS

Respuesta

48

Si no puede agregar un objeto de fábrica como lo sugiere skaffman, puede usar DateTimeUtils.setCurrentMillisFixed().

+7

Un comentario tan agradable, me gustaría dos veces. –

+5

Quizás desee restablecerlo de nuevo al sistema con 'setCurrentMillisSystem' después de las afirmaciones de prueba. –

+6

Esta API modifica una variable global y, por lo tanto, debe evitarse. –

14

Luego hay que definir una interfaz Clock, e inyectarla en la clase

public interface Clock { 
    DateTime getCurrentDateTime(); 
} 

a continuación:

Clock clock; 

public FirmOrder findActiveByModelColor(ModelColor modelColor) { 
    Query query = em.createQuery("FROM FirmOrder fo WHERE fo.modelColor = :modelColor AND fo.year = :year AND fo.month = :month"); 
    query.setParameter("modelColor", modelColor); 
    query.setParameter("year", clock.getCurrentDateTime().year().get()); 
    query.setParameter("month", clock.getCurrentDateTime().dayOfMonth().get()); 
    return (FirmOrder) query.getSingleResult(); 
} 

Su prueba puede luego inyectar una implementación de Clock (p. utilizando un marco de burla) que siempre devuelve un tiempo fijo.

Uso la interfaz Clock mucho en mis propias cosas, y sigo sorprendido de que no sea parte de una de las bibliotecas comunes que hay. Tengo dos implementaciones que uso mucho, WallClock y StoppedClock (que es útil para las pruebas que usan un tiempo fijo).

+0

Me gusta tu idea. Pero tengo una pregunta de pareja que quiero preguntar. 'Clock # getCurrentDateTime()' me devolverá el actual 'JodaTime # DateTime', que es genial. Sin embargo, necesito comparar el DateTime actual a las 4 p.m. EST. En mi código, tengo este 'fourPM = new DateTime (current.getYear(), current.getMonthOfYear(), \t \t \t \t current.getDayOfMonth(), 16, 0, 0, 0, DateTimeZone.forID (" EST "));' for 'current = new DateTime()' –

+0

@Harry: Necesitas hacer una nueva pregunta – skaffman

+0

Acabo de crear una nueva pregunta. http://stackoverflow.com/questions/6049777/mockito-how-to-mock-an-interface-of-jodatime Por favor, ayuda –

1

Es fácil, si se utiliza el JMockit expectativas burlarse API:

@Test 
public void findActiveByModelColor() 
{ 
    new NonStrictExpectations() 
    { 
     @Cascading DateTime dt; 

     { 
      dt.year().get(); result = 2010; 
      dt.monthOfYear().get(); result = 12; 
     } 
    }; 

    FirmOrder fo = testedObject.findActiveByModelColor(modelColor); 

    // asserts... 
} 
+1

JMockit es excelente para probar código mal escrito. – IAdapter

+0

Entonces, ¿el código que usa 'DateTime' (o' java.util.Date') como este siempre es malo? ¿Qué pasa con el código que utiliza Apache Commons Email API, que ejemplifica un objeto 'SimpleEmail' y llama' send() 'sobre él? ¿Es un código malo? ¿Por qué? –

4

Parece que la única opción es utilizar la función de respuesta para publicar este comentario:

La siguiente parte de su código puede conducir a difíciles de detectar errores:

query.setParameter("year", new DateTime().year().get()); 
query.setParameter("month", new DateTime().monthOfYear().get()); 

Vamos a suponer tha hoy es el último día del año 2011 y esta parte del código que se llama nano 1 segundo antes del nuevo año y que la primera declaración toma más de 1 nano segundo para completarse. Esto significa que el año se fijará en 2011 pero en el mes en 1, pero fue mejor para 2011/12 o 2012/1.

A pesar de que estadísticamente es muy poco probable que suceda, pero lógicamente puede suceder :)

Debe crear una instancia DateTime y usarlo para rellenar los dos year y month.

+1

Está bien, esa no es realmente una respuesta al OP, pero lo voté porque hay más personas que deben conocer este problema. Dado que muchas tiendas empresariales (y configuraciones domésticas) compilan durante las horas nocturnas (como las 11:30 PM), este error es, en realidad, sorprendentemente común y molesto. Suele ser más sutil, pero es por eso que el StoppedClock mencionado en otra respuesta es una buena idea. –

Cuestiones relacionadas