【问题标题】:Testing time-dependent service method测试依赖时间的服务方法
【发布时间】:2012-05-08 23:31:58
【问题描述】:

我正在尝试使用在数据库表中查找当前“处理周期”的方法为服务编写集成测试。但是,并不总是有一个有效的处理周期,因此该方法可能会返回 null(有几周没有进行处理)。我想为这个方法写一个 JUnit 测试,但由于它不会总是返回一个值,我会根据我运行测试的时间得到不同的结果。

期间对象和服务看起来像:

public interface ProcessingPeriod {
    int getSeqno();
    Date getStart();
    Date getEnd();
}

public class PeriodService {
    /* Look up the current period; if not currently in a period, return null */
    public ProcessingPeriod getCurrentPeriod() { /* execute a sql query */ }

    /* Look up the current period; if not currently in a period, get the next upcoming period */
    public ProcessingPeriod getCurrentOrNextPeriod() { /* execute a sql query */ }

    /* Look up the current period; if not currently in a period, get the most recent period */
    public ProcessingPeriod getCurrentOrPreviousPeriod() { /* execute a sql query */ }
}

PeriodService 的实例由 Spring 应用程序上下文管理,我的 JUnit 测试使用 SpringJUnit4ClassRunner 构造测试上下文并为测试提供服务对象。我的 JUnit 测试目前看起来像:

@Test
public void testGetCurrentPeriod() {
    ProcessingPeriod period = service.getCurrentPeriod();
    if (period != null) {
        Date now = new Date();
        assertThat(period.getStart(), lessThanOrEqualTo(now));
        assertThat(period.getEnd(), greaterThanOrEqualTo(now));
    }
}

但是,如果在处理期间不运行测试,这似乎没有多大帮助。我怎样才能有意义地测试getCurrentPeriod 方法实际上从数据库中获取了正确的时间段?我应该嘲笑数据库吗?我还想对数据库实际执行查询,以帮助确保 SQL 有效。

【问题讨论】:

标签: java testing junit mocking integration-testing


【解决方案1】:

我没有在我的代码中使用 new Date()getCurrentTimeMillis() 等。我总是使用包含我需要的所有时间相关方法的时间提供程序。

interface TimeProvider {
  Date getDate();
  int getCurrentQuarter();
  ...
}

生产实现是显而易见的。但是,对于测试,您可以放置​​所需的任何提供程序,以便您可以在测试中设置任何时间。它适用于春天。但它仅在您测试不使用它自己的内部时钟(睡眠、锁定、石英等)的代码时才有效。

看起来它适合您的示例,但您必须重构您的生产代码

【讨论】:

  • 谢谢,这也许是可能的;尽管当前查询使用的是数据库中的当前日期时间,因为我们将其视为整个组织的权威。
  • 如果需要数据库日期,那么您应该重构查询,以便将日期作为参数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-10
  • 2012-12-23
相关资源
最近更新 更多