如何在BDD中创建良好的可重复日期测试?

时间:2014-12-22 11:20:06

标签: java spring bdd concordion

当我在数据库中插入业务对象时(使用spring / hibernate),有一些日期字段会使用当前日期更新。

这是一个重要的功能,所以我想在我的可测试规范中验证它。

问题在于我希望看到具有正确日期的字段,但由于它是当前日期,因此每次都会更改。

我有一个可以奏效的解决方案,但是它非常好,以至于我无法在良心上做到这一点。

就像这样:

@Service
public class DateService {
  private Date fixedDate;

  public Date getCurrentDate() {
    if (fixedDate != null)
      return fixedDate;
    return new Date();
  }

  // setter / reset
}

每次我需要一个新的Date()时,我都会自动启动它。然后,当它的测试时间,我确定日期,所以我知道每个"新"日期将是这个日期。

如何在项目中创建良好的可重复的基于日期的测试?

由于

3 个答案:

答案 0 :(得分:1)

我会以下列方式接近它:

  1. 在测试客户端中,我会捕获当前日期并将其保存在变量
  2. 然后我会调用要测试的服务(服务应该获取当前日期并使用它来更新模型)
  3. 然后我会调用该服务来获取模型的相关部分(CR中的R);我假设模型表示包含具有日期
  4. 的字段
  5. 然后我会写一个断言来比较2个日期:我在测试客户端获得的日期和服务设置的日期

答案 1 :(得分:1)

如果您可以更改底层系统,则注入备用时钟实现效果很好。例如,this answer显示了各种解决方案,包括Java 8的java.time.Clock接口。

对于要测试实际实现的系统测试,请使用Concordion规范,例如:

<p>The invoice date is set to <span c:assertEquals=getInvoiceDate()>today</span></p>

从fixture方法返回一个String值,包含:

  • “今天”如果日期是今天,或
  • 如果日期不是今天的格式化日期。然后,这将在Concordion输出中显示为 today 20/12/2014。

注意:使用这种方法时,请注意在午夜运行测试,因为您在检索日期和测试日期之间存在日期更改的风险。

答案 2 :(得分:0)

为了防止在生产环境中使用测试代码,我建议使用mock / stub框架来替换测试中的DateService。 例如,您可以使用Mockito(https://github.com/mockito/mockito)创建DateService的测试实例,返回固定日期:

Date fixedDate = new Date(); //use any settings you need for your test
DateService mockedDateService = mock(DateService.class);
when(mockedDateService.getCurrentDate()).thenReturn(fixedDate);