2010-12-30 3 views
3

Я хочу издеваться над конструктором по умолчанию java.util.date, поэтому он не создает a Date объект, представляющий время, когда он был создан, но всегда тот же Date объект (в моем примере ниже 31 декабря 2010 года). Я пробовал делать это с JMockit и JUnit, но при выполнении моего теста ниже вывод всегда Thu Jan 01 01:00:00 CET 1970. Так что же не так с моим макетом Date()?Как высмеять конструктор по умолчанию класса Date с помощью 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! 
     } 
    } 
} 

ответ

9

Ответ al nik был хорошим намеком для меня. Лучше высмеять класс System вместо класса Date, чтобы создать поддельное время. Мое собственное решение в итоге было просто издеваться над методом System.currentTimeMillis() (этот метод вызывается внутренним образом Date()).

JMockit 1,5, а затем

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 и более ранних версий

@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

Вы издевались конструктор, и внутри вы сделали экземпляр Date (который не имеет ничего общего с построенным) и просто выбросил. Поскольку конструктор по умолчанию издевается, дата не инициализируется текущим временем, и поэтому вы получаете нулевое значение (которое представляет собой результат 1970-01-01).

Чтобы изменить возвращаемую дату нужно использовать магию «это» атрибут, как так:

@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

Я попытался это, но он дал мне 'NullPointerException в AppTest $ MockedDate. $ INIT (AppTest. java) в java.util.date. '. – asmaier

+0

Странно, я просто попробовал, и он работает, используя текущий jmockit. – fdreger

+0

привет, могу ли я установить другой объект Date в «it»? 'it = new Date (...)' –

9

Как указывается в Test Driven книги, это хорошая практика, чтобы использовать SystemTime абстракцию в классах Java. Замените вызовы методов (System # currentTimeMillis и календарь # GetInstance) и прямое строительство (новая дата()) со статическим методом вызовов, такие как:

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

подделать время вам просто нужно изменить, что возвращенный SystemTime класс.
SystemTime использовать TimeSource интерфейс, который делегаты по умолчанию для System.currentTimeMillis()

public interface TimeSource { 
    long millis(); 
} 

конфигурируемый реализация SystemTime может быть что-то вроде этого

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

и подделать возвращенное время вы просто сделать

@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 упрощает работу с датами на Java и предлагает вам некоторые вещь вроде этого из коробки

Смежные вопросы