【问题标题】:Can't mock Date class不能模拟 Date 类
【发布时间】:2013-08-04 21:58:32
【问题描述】:

我正在使用 mockito,我有一个自定义日期类,我希望能够在我的测试类中模拟这个日期类,所以我尝试了以下方法:

    MVDate date = Mockito.mock(MYDate.class);
    Mockito.when(date.get(Calendar.MONTH)).thenReturn(5);

MYDate 类:

public class MYDate extends GregorianCalendar implements Comparable<Calendar> {

public MYDate() {
        setTime(new Date());
    }

}

但是当尝试打印new MYDate(); 时,它总是打印当前日期。 请告知我应该如何模拟日历类,以便我可以在特定日期测试创建新数据实例的所有方法。

【问题讨论】:

  • 日期不是日历...
  • 您能否发布一些代码,以便我们了解发生了什么?如果您正在使用 new Date(),那么您将不会使用您的 Calendar 模拟。
  • @David Wallace 我更新了问题。
  • @assylias,我更新了问题。

标签: java unit-testing junit mocking mockito


【解决方案1】:

请注意:我在 2013 年写了这个答案。现在情况有点不同了。 Basil Bourque 的答案是正确的。

我会使用 Factory 类来制作 Date 对象,而不是使用 new Date()。为MyDate 提供第二个构造函数,您可以在其中传递工厂。然后使用工厂的模拟,您可以设置它以返回您喜欢的任何日期。

public class DateFactory{
    public Date makeDate(){
        return new Date();
    }
}

-----------------------------------

public class MyDate extends GregorianCalendar implements Comparable<Calendar>{

    public MyDate(){
        this(new DateFactory());
    }

    MyDate(DateFactory factory){
        setTime(factory.makeDate());
    }
}

【讨论】:

  • 你能分享我如何在测试中使用 DateFactory 吗?
  • 如我所说。你模拟了工厂。当您调用makeDate 时,您将其存根以返回您希望它返回的任何日期。在您的测试中,您使用第二个 MyDate 构造函数并传入模拟工厂。
【解决方案2】:

因此,针对获取当前日期的代码编写单元测试的需求非常普遍。我与它斗争了无数次,最后写了一个解决方案。我的解决方案是使用DateSupplier 来包装对new Date() 的调用。然后我有一个名为DateController 的测试类,它允许单元测试控制DateSupplier 返回的值。

以下是链接: DateSupplier

DateController

DateSupplier 是用static 方法编写的,以获取Date。这可以防止编码人员不得不在各处导入实例。

DateController 写成Rule,它将DateSupplier 的行为恢复为返回new Date() 的默认行为。

【讨论】:

  • DateSupplier 可以更优雅地命名:Clock
  • @John B,我应该为 jboss 上的 ParametersAreNonnullByDefault 注释使用什么 jar?我也可以使用没有此注释的示例吗?
  • 是的,注释只是文档。它在jsr305中提供
  • 这在 Kotlin 中几乎不可能实现,因为 getInstance() 受到保护。
【解决方案3】:

Java 8 java.time.Clock

Java 8 中的新 java.time.* package 包含一个 Clock 类,用于在开发和测试期间模拟日期时间。

乔达时间

我记得,流行的Joda-Time 框架也有一个伪造时钟的工具。

转换

您可以根据需要在这些框架的日期时间对象和 java.util.Date 类之间轻松转换,以实现互操作性。

【讨论】:

    【解决方案4】:

    在您的代码中,您正在模拟一个特定的方法“cal.get()”。

    assertEquals(cal.get(Calendar.MONTH), 5);
    

    在这种情况下,上面的语句是正确的,但是 cal.getTime() 会返回一些不同的东西。您的意思是要模拟 cal.getTime() 吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      • 2022-06-29
      • 2018-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多