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

How to prepare for integration tests which use PostgreSQL's in memory replacement?

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

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

如果有none,我该如何进行集成测试

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

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

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

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

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

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

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

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

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

  1. testcontainers会帮你提供 真实数据库

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

    缺点:

    • 创建和维护架构和数据需要大量工作。特别是当您的项目处于密集开发阶段时。
    • 它是另一个抽象层,因此如果您突然想使用此工具不支持的某些数据库功能,可能很难对其进行测试
  3. testegration - 旨在为您提供完整的、随时可用且可扩展的生命周期(披露:我是创作者)。

    缺点:

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

另一个步骤是将数据库移动到 OS 级别的内存中。同样,首次启动时间与需要加载的所有内容相似。一些起点 here and here

缺点:

  • 你团队中的每个开发人员都必须修改他的本地环境
  • 在 OS 之间不可移植(如果您的团队有异构环境)

您实际上可以让真正的 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

这与您可以使用真实产品获得的 "in-memory" 非常接近。

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

我写了一个小库来帮助您快速将数据库恢复到 'clean' 状态。这样你只需要运行一次昂贵的数据库迁移,然后你就可以为每个测试快速恢复数据库。

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

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