如何在单元测试期间使jOOQ使用测试表?

时间:2018-02-18 10:13:46

标签: java postgresql unit-testing hsqldb jooq

我正在努力弄清楚如何对持久性级别方法进行单元测试。为了生产,我使用postgres,我有jOOQ从我的数据库模式生成Java类。为了测试,我已经配置了一个内存中的HSQLDB,并为spring创建了一个schema.sql文件,以创建一个与生产数据库中的表完全匹配的表,每个配置都在src或test中的单独application.yaml文件中。

现在问题就在于此。我的持久层有方法,直接引用由jOOQ生成的表类,显然是因为只有该类具有与各列对应的成员字段。一个例子:

private Data DATA = Tables.DATA;

public Timestamp findLatestNonRealtimeClose(String ticker) {
    return (Timestamp) jooq
            .select(max(DATA.DATE))
            .from(DATA)
            .where(DATA.TICKER.eq(ticker))
            .and(DATA.REALTIMECLOSE.eq(Boolean.FALSE))
            .fetch()
            .getValue(0, 0);
}

该方法只返回给定股票代码的最新现有日期条目。在编写测试时,此方法仍将转到实际生产数据库,而不是测试数据库。我不能将表作为jOOQ中存在的多态参数类型表传递,因为我必须将其转换为Tables.DATA才能访问列。如果我想使用测试数据库,我甚至不知道要将它转换为什么类型,因为HSQLDB表没有运行时Java表示,即使我这样做,该方法也不知道如果它是作为测试的一部分运行。如何重写方法以考虑测试或生产运行?

在Lukas Eder撰写的an article中,据说您不应该对您的数据库代码进行单元测试,但我仍然希望这样做。

2 个答案:

答案 0 :(得分:2)

替换您的测试环境的jOOQ Configuration

我不确定为什么你认为jOOQ表引用是这里的问题。您应该能够毫不费力地针对任何类型的数据库运行完全相同的jOOQ查询。唯一的区别应该是您配置jooq实例的方式(即DSLContext及其Configuration):

  • 制作:使用现有实例
  • 测试:将其替换为连接到HSQLDB并使用SQLDialect.HSQLDB
  • 的实例

单元测试与集成测试

  

在Lukas Eder撰写的一篇文章中,据说你不应该对你的数据库代码进行单元测试,但我仍然愿意这样做。

你误解了我所说的"单元测试",以及我所说的"集成测试" (这就是你正在做的事情)。在我看来,后者完全没问题。当然,我总是建议将您的应用程序与生产数据库产品(例如PostgreSQL,例如Docker)集成测试,但如果有充分理由不这样做,那么HSQLDB就足够了。

单元测试(根据我的定义)将数据库替换为任何级别的模拟,包括:

我文章的批评表明,在某些时候,模拟数据库等同于实现数据库,所以为什么不使用现成的数据库进行集成测试呢。

答案 1 :(得分:1)

你可以模拟整个调用链......

when(jooq.select()).thenReturn(whereMock); 
when(whereMock.from(DATA)).thenReturn(fromMock);

等等;然后验证一切都被正确调用。