2010-12-30 7 views
3

Ich möchte den Standardkonstruktor von java.util.date mock, so dass es kein ein Date Objekt darstellt, das die Zeit darstellt, als es erstellt wurde, aber immer das gleiche Date Objekt (in meinem Beispiel unter 31 Dez 2010). Ich habe versucht, dies mit JMockit und JUnit, aber bei der Ausführung meiner Test unten ist die Ausgabe immer Thu Jan 01 01:00:00 CET 1970. Also, was ist los mit meinem Mock von Date()?Wie spottet man den Standardkonstruktor der Date-Klasse mit JMockit?

import java.util.Date; 

import org.junit.*; 
import mockit.*; 

public class AppTest { 

    @Before 
    public void setUp() { 
     Mockit.setUpMocks(MockedDate.class); 
    } 

    @After 
    public void tearDown() { 
     Mockit.tearDownMocks(); 
    } 

    @Test 
    public void testDate() { 
     Date today=new Date(); 
     System.out.println(today.toString()); 
    } 

    @MockClass(realClass=Date.class) 
    public static class MockedDate { 

     @Mock 
     public void $init() { 
      // Now should be always 31.12.2010! 
      new Date(110,11,31); //110 = 2010! 11 = December! This is sick! 
     } 
    } 
} 

Antwort

9

al Nik Antwort war ein guter Hinweis für mich. Es ist besser, die System Klasse statt der Date Klasse zu verspotten, um eine falsche Zeit zu generieren. Meine eigene Lösung war am Ende einfach die System.currentTimeMillis() Methode zu verspotten (diese Methode wird intern von Date() aufgerufen).

JMockit 1.5 und höher

new MockUp<System>(){ 

    @Mock 
    public long currentTimeMillis() { 

     // Now is always 11/11/2011 
     Date fake = new Date(111,10,11); 
     return fake.getTime(); 
    } 
}; 

JMockit 1.4 und früher

@MockClass(realClass = System.class) 
public static class MockedSystem { 

    @Mock 
    public long currentTimeMillis() { 

     // Now is always 11/11/2011 
     Date fake = new Date(111,10,11); 
     return fake.getTime(); 
    } 
} 
0

Sie verspotteten den Konstruktor, und im Inneren eine Instanz von Date gemacht (das hat nichts mit dem zu tun gebaut) und warf ihn einfach weg. Da der Standardkonstruktor mokiert ist, wird das Datum nicht auf die aktuelle Zeit initialisiert, und Sie erhalten die Zeit von Null (die 1970-01-01 darstellt).

das zurückgegebene Datum ändern Sie, wie so ein magischen „es“ -Attribut, verwenden müssen:

@MockClass(realClass=Date.class) 
public static class MockedDate { 

    public Date it; 
    @Mock 
    public void $init() { 
     // This is sick! 
     it.setDate(31); 
     it.setYear(110); // 110 = 2010! 
     it.setMonth(11); // 11 = December! 
    } 
} 
+0

ich das versucht, aber es gab mir einen 'Nullpointer bei AppTest $ MockedDate. $ Init (AppTest. Java) bei java.util.date. '. – asmaier

+0

Seltsam, ich habe es gerade versucht und es funktioniert, mit aktuellen jmockit. – fdreger

+0

Hallo, kann ich ein anderes Date-Objekt auf "it" setzen? 'it = neues Datum (...)' –

9

Wie im Buch Test Driven vorgeschlagen ist es empfehlenswert, eine Systemtime Abstraktion in Ihren Java-Klassen zu verwenden. Ersetzen Sie Ihre Methodenaufrufe (System # currentTimeMillis und Kalender # getInstance) und direkte Konstruktion (new Date()) mit statischer Methode ruft wie:

long time = SystemTime.asMillis(); 
Calendar calendar = SystemTime.asCalendar(); 
Date date = SystemTime.asDate(); 

zu fälschen die Zeit, die Sie brauchen nur zu ändern, was von Ihrem Systemtime zurückgegeben Klasse.
Systemtime verwenden, um eine Timesource-Schnittstelle, die auf System.currentTimeMillis von Standard Delegierten()

public interface TimeSource { 
    long millis(); 
} 

eine konfigurierbare Systemtime Implementierung so etwas wie dieses

und zu fälschen die zurückgegebene Zeit, die Sie einfach

tun
public class SystemTime { 
    private static final TimeSource defaultSrc = 
      new TimeSource() { 
       public long millis() { 
        return System.currentTimeMillis(); 
       } 
      }; 

    private static TimeSource source = null; 
    public static long asMillis() { 
     return getTimeSource().millis(); 
    } 

    public static Date asDate() { 
     return new Date(asMillis()); 
    } 
    public static void reset() { 
     setTimeSource(null); 
    } 
    public static void setTimeSource(TimeSource source) { 
     SystemTime.source = source; 
    } 
    private static TimeSource getTimeSource() { 
     return (source != null ? source : defaultSrc); 
    } 
} 
sein könnte
@Test 
public void clockReturnsFakedTimeInMilliseconds() throws Exception { 
    final long fakeTime = 123456790L; 
    SystemTime.setTimeSource(new TimeSource() { 
     public long millis() { 
       return fakeTime; 
     } 
    }); 
    long clock = SystemTime.asMillis(); 
    assertEquals("Should return fake time", fakeTime, clock); 
} 

Joda-Time library vereinfacht das Arbeiten mit Daten in Java und bietet Ihnen einige Ding wie das aus der Box