使用 H2 数据库对 DAO 层进行单元测试

Posted

技术标签:

【中文标题】使用 H2 数据库对 DAO 层进行单元测试【英文标题】:Unit testing DAO layer with H2 database 【发布时间】:2019-11-15 09:37:04 【问题描述】:

在互联网上大量阅读后,我发现使用像 H2 这样的内存数据库对 DAO 层进行单元测试似乎是一个好习惯。背后的想法是避免使用生产数据库。

很好,所以我设置了一个 H2 数据库并激活了 H2 PostgreSQL 兼容模式,因为我的生产数据库在 Postgres 上。我现在面临的问题:当我在 H2 上运行原始 SQL 查询以构建测试数据库时,H2 不接受此查询为有效:

ALTER SEQUENCE MYERP.ecriture_comptable_id_seq OWNED BY MYERP.ecriture_comptable.id;

我猜想使用 PostgreSQL 兼容模式并不能保证所有 Postgres 特定的语法都会被 H2 接受。并且可能这也会发生在其他数据库(例如 mysql)上。

那么在这种情况下使用 h2 数据库有什么意义呢? 我错过了什么吗?

【问题讨论】:

"*那么在这种情况下使用 h2 数据库有什么意义?" - 没有。我从来不明白为什么人们认为那些会是有效的测试。我确实认为使用不同的 DBMS 进行测试和生产是“好的做法”。其实我觉得没用 【参考方案1】:

单元测试应该专注于测试一个单元。 PostgreSQL 在您的应用程序外部,因此不属于任何使用它的 DAO:不应编写使用任何此类外部数据库的“单元测试”。

使用数据库进行集成测试可能很好,但是您已经注意到,当您使用不同的数据库执行集成测试时可能会出现多个问题(我知道很少有应用程序只使用 ANSI-SQL 而没有任何触发器或其他供应商特定的 SQL 扩展,如 PostgreSQL 案例中的 UPSERT 或您帖子中的 SQL)。

如果您的生产基地也在内存中怎么办?这非常困难,我认为集成测试会很好,只是不要将其称为单元测试。所有这些只是突出了在数据库中执行业务逻辑(例如,通过您现在无法测试的触发器)或使用特定于供应商的 sql 的痛点,后者具有在更改底层数据库供应商时效果不佳的几个优点。

【讨论】:

我的目的是测试 DAO 层的所有 CRUD 方法是否都能正常工作。我们认为它确实更像是一个集成测试而不是一个单元测试。无论如何,我现在认为直接测试 Postgre DB 会更有意义,而不是使用 H2 数据库进行测试。如果我注意不改变数据库的状态(使用回滚),这应该没问题。你怎么看? 您总是可以让测试在 Docker 容器或其他东西中启动一个新的 PostgreSQL 实例,创建表,进行测试并将其拆除。使用共享数据库(例如测试实例的)是有风险的,因为在执行集成测试时它无法用于维护。不过,这样的测试没有任何问题,只要它是一个集成测试。这种东西总是很烦人,当你周围没有 Docker(或类似的东西)时更是如此 其实我收到了一个关于Docker的demo数据库。所以我想我应该利用它! 很高兴听到,祝你一切顺利!如果您需要更多帮助,请随时回来 感谢您的帮助!

以上是关于使用 H2 数据库对 DAO 层进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章

使用 Mockito 对 DAO 层进行单元测试

spring mvc中的单元测试

内存中带有 derby 的单元测试数据库层 DAO

如何使用 Spring Security 对 Spring 4 DAO 方法进行单元测试?

2编写单元测试用例,对用户注册功能的DAO层进行测试。(注意:测试用例应考虑成功和失败的情况)

如何在 Java 中对 DAO 应用单元测试