【问题标题】:Junit with new Date()带有新日期()的 Junit
【发布时间】:2011-02-23 14:12:04
【问题描述】:

当我有以下方法时,junit 测试会是什么:

@Override
public void saveLastSuccesfullLogin(final User user) {
    gebruiker.setLastLogin(new Date());
    storeUser(user);
}

子方法 storeUser:

@Override
public void storeUser(final User user) {
    EntityManager em = emf.createEntityManager();

    em.getTransaction().begin();
    em.merge(user);
    em.getTransaction().commit();

    em.close();
}

我遇到的问题是日期,为实体用户设置然后存储。我正在使用 junit 和 easymock。

【问题讨论】:

    标签: date junit easymock


    【解决方案1】:

    尝试将 new Date() 拉入具有默认访问说明符的方法中,如下所示

    @Override
    public void saveLastSuccesfullLogin(final User user) {
        gebruiker.setLastLogin(getDate());
        storeUser(user);
    }
    Date getDate() {
        return new Date();
    }
    

    在您的测试类中,使用模拟或存根日期覆盖下面的类。

    <ClassUnderTest> classUnderTest = new <ClassUnderTest> () {
      @Override 
      Date getDate() {
        return mockDate;
      } 
    }
    

    通过这种方式,您可以轻松地断言日期值,因为它将被删除。

    【讨论】:

    • 我不会用匿名类覆盖,而是使用Mockito's partial mock。所以它将是 ClassUnderTest t = spy(new ClassUnderTest()); when(t.getDate()).thenReturn(DATE_MOCK);
    【解决方案2】:

    日期有什么问题?你不知道以后要断言什么?一些替代方案:

    1. 将日期传递给方法
    2. 创建工厂以获取当前日期/时间,以便您可以模拟出来
    3. 在正确性阈值内断言日期

    【讨论】:

      【解决方案3】:

      还有一种更“企业级”的方法可以用于依赖注入可用的地方(如 EJB、Spring 等)。

      您可以定义一个接口,例如TimeService,并添加返回当前日期的e方法。

        public interface TimeService {
          Date getCurrentDate();
        }
      

      您可以实现它以返回 new Date() 并像这样使用它:

        gebruiker.setLastLogin(timeService.getCurrentTime());
      

      这显然很容易测试,因为您可以模拟TimeService。使用 EasyMock(只是一个例子),这可能是:

        Date relevantDateForTest = ...
        expect(timeService.getCurrentTime()).andReturn(relevantDateForTest);
        replay(timeService);
      

      在整个代码中使用TimeService 而从不使用new Date() 是一种非常好的做法,并且还有其他优点。我发现它在很多场合都有用,包括对将来会激活的功能进行手动功能测试。更进一步,系统时间可以从外部系统中检索,从而使其跨集群等保持一致。

      【讨论】:

      • 我写了一个更详细的post here 供那些希望了解更多关于使用单独服务检索当前日期的信息。
      【解决方案4】:

      您还可以创建一个 getDate 方法和一个日期静态变量:

          private static Date thisDate = null;
      
          @Override
          public void saveLastSuccesfullLogin(final User user) {
              gebruiker.setLastLogin(getDate());
              storeUser(user);
          }
      
          public Date getDate() {
              if(thisDate != null) return thisDate;
              return new Date();
          }
      
          public void setDate(Date newDate) {
              thisDate = newDate;
          }
      

      然后在您的测试方法中,您可以继续调用 setDate 来控制您将获得的日期。

      【讨论】:

        猜你喜欢
        • 2018-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-25
        相关资源
        最近更新 更多