如何准备在内存替换中使用 PostgreSQL 的集成测试?

Posted

技术标签:

【中文标题】如何准备在内存替换中使用 PostgreSQL 的集成测试?【英文标题】:How to prepare for integration tests which use PostgreSQL's in memory replacement? 【发布时间】:2017-09-15 13:47:01 【问题描述】:

我了解到,在集成测试中使用实际数据库会显着降低它们的速度。因此,我必须使用内存数据库,这可能会显着提高集成测试的速度。

我正在使用 Springboot 进行应用程序开发。我如何配置 PostgreSQL 以进行测试?有没有与PostgreSQL语法高度兼容的内存数据库?

如果没有,我应该如何进行集成测试。

【问题讨论】:

An example with Test Container - support most DB 【参考方案1】:

我在真实 postgres 上的一些数据库测试每次需要 10 毫秒。我在每个测试中进行多次提交。所以:

要覆盖 postgres-native 特性,您需要相同的数据库(如您所见,h2 和其他内存数据库不是很兼容)。 postgres 没有内存模式。 对于功能测试,真实数据库本身并不比任何内存数据库慢多少。区别通常在于启动时间(对于 postgres 9.6,它大约是 4 秒)。但是,如果您的测试生命周期很智能,并且您可以将 db 开始数减少到 1 或 0(通过让开发数据库始终准备好),那么问题就不再那么明显了。

所以获取真正的 postgres 并正确设置它的生命周期。有一些工具可以帮助您解决一些问题:

    testcontainers 将帮助您提供 真正的数据库。

    dbunit - 将帮助您清理测试之间的数据

    缺点:

    创建和维护模式和数据需要做很多工作。尤其是当您的项目处于密集开发阶段时。 它是另一个抽象层,所以如果您突然想使用该工具不支持的某些 db 功能,可能很难对其进行测试

    testegration - 旨在为您提供完整、随时可用和可扩展的生命周期(披露:我是一个创造者)。

    缺点:

    仅对小型项目免费 非常年轻的项目

另一个步骤是将数据库移动到操作系统级别的内存。同样,第一次启动时间将相似,因为所有内容都需要加载。一些起点here和here

缺点:

团队中的每个开发人员都必须修改其本地环境 操作系统之间不可移植(如果您的团队有异构环境)

【讨论】:

【参考方案2】:

这个问题征求意见,但这里是:

如果您想测试将使用 PostgreSQL 的应用程序,则必须使用 PostgreSQL 进行测试。 SQL 方言和行为在不同的数据库管理系统之间差别太大。

如果您使用足够小以适合 RAM 的数据库,则可以使 PostgreSQL 变得非常快,这对于只针对功能而非整体性能的集成测试应该是可能的。

【讨论】:

问题还提到了“如何?”部分。 不需要特殊配置。如果有足够的 RAM 以使数据库适合它而不会产生内存压力,那么它将保持在那里。如果您不想依赖文件系统缓存,请将shared_buffers 设置得足够大,以便整个数据库都适合。【参考方案3】:

您实际上可以让一个真正的 Postgres 在测试环境中安静地运行。

我还建议您使用 dockerized 数据库,但使用 tmpfs 对数据文件夹进行内存映射:

docker run --name postgres95 -p 5432:5432 --tmpfs /var/lib/postgresql/data:rw -e POSTGRES_PASSWORD=admin -d postgres:9.5.6

这与您可以使用真实事物获得的“内存中”一样接近。

我认为慢速集成测试的主要问题之一不是数据库本身的性能,而是为每个测试设置它所花费的时间。

我编写了一个小库来帮助您快速将数据库恢复到“干净”状态。这样您只需要运行一次代价高昂的数据库迁移,然后您就可以为每次测试快速恢复数据库。

我们在生产系统中使用它以在我们的集成测试中获得 4 倍的加速:

https://github.com/ayedo/postgres-db-restore

【讨论】:

【参考方案4】:

您如何访问应用程序中的数据库?使用普通 JDBC 还是在其之上使用抽象 (JPA)?

如果您使用抽象层,例如JPQL,所以方言不是那么重要,也许您可​​以使用in-memory H2 数据库进行测试。

如果您必须使用原生 PostgreSQL 语句,另一种方法是使用使用 Testcontainers 的 dockerized 数据库。这不会加快测试速度,但会使设置/清理环境更加容易。

【讨论】:

我用mybatis访问 这应该适用于 H2:blog.lanyonm.org/articles/2014/04/21/… 为什么它适用于 H2? Mybatis 是否只支持 PostgreSQL 的子集功能,顺便兼容 H2? 那么您需要原生 PostgreSQL 功能吗?比你必须使用真正的 PostgresSQL 数据库。也许 Testcontainers 会派上用场。

以上是关于如何准备在内存替换中使用 PostgreSQL 的集成测试?的主要内容,如果未能解决你的问题,请参考以下文章

如何在postgresql中替换URL中的值

postgresql - 替换文本字段中字符串的所有实例

如何在 postgresql 中用它的根替换一个单词?

在 postgresql 中使用替换更新语句

在 PostgreSQL 中准备、存储、检索加密数据

PostgreSQL/JDBC - 如何准备调用带有参数 CITEXT (TEXT) 的函数?