java:如何模拟Calendar.getInstance()?

在我的代码中我有这样的事情:

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

如何在我的junit测试中“模拟”它以返回特定的日期?

据我所知,你有三个合理的选择:

  1. 在您当天设置的任何方法/类中注入Calendar实例。

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

  2. 使用JodaTime而不是Calendar 。 这不是一个选择,而是一个建议的案例,因为JodaTime将使您的生活更轻松。 您仍然需要将此时间注入方法。

    DateTime dt = new DateTime();

    Date jdkDate = dt.toDate();

  3. 在一些允许您获取时间的界面中包装Calendar 。 然后,您只需模拟该接口并使其返回一个常量Date

    Date today = calendarInterfaceInstance.getCurrentDate()

你可以使用PowerMock和Mockito一起模拟它:

在课堂上:

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

成功的关键是你必须将类放在PrepareForTest中使用Calendar而不是Calendar本身,因为它是一个系统类。 (在我发现这个之前,我个人不得不经常搜索)

然后嘲笑自己:

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

不要嘲笑它 – 而是引入一个你可以模拟得到日期的方法。 像这样的东西:

 interface Utility { Date getDate(); } Utilities implements Utility { public Date getDate() { return Calendar.getInstance().getTime(); } } 

然后你可以将它注入到你的类中,或者只使用带有一堆静态方法的helper类和一个load方法:

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

然后在您的应用程序代码:

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

然后,您可以在测试方法中加载模拟接口。

 @Test public void shouldDoSomethingUseful() { Utility mockUtility = // .. create mock here AppUtil.load(mockUtility); // .. set up your expectations // exercise the functionality classUnderTest.doSomethingViaAPI(); // ... maybe assert something } 

另请参阅您是否只能模拟您拥有的类型? 和测试气味 – 一切都被嘲笑

使用Mockito和PowerMockito:

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

有关完整代码,请参阅链接 。

使用返回Calendar.getInstance() DateHelper方法编写一个名为DateHelper的类。 重构您正在测试的类,使其具有DateHelper类型的成员变量,以及注入该成员变量的构造函数。 在测试中使用该构造函数,以注入DateHelper的模拟,其中DateHelper已被存根以返回某个已知日期。

你可以使用JMockit进行模拟。 在这里,您可以看到如何做到这一点: 模拟Java日历 – JMockit与Mockito 。

对于那些遵循MVP模式的人来说,日历是小菜一碟:

  1. 在Presenter中创建一个返回日历实例的方法:

      public Calendar getCurrentTime() { return Calendar.getInstance(); } 
  2. 在您的视图(活动,片段等)中,您可以在演示者的帮助下访问日历:

      Calendar calendar = mPresenter.getCurrentTime(); // do whatever you want 
  3. 在您的测试中,您可以:

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