在 Spring Boot 上下文中使用 h2db 进行集成测试是不好的做法吗?

问题描述

我们的团队最近提出了一个问题,如果生产环境依赖于不同的数据库引擎(在我们的例子中是 MysqL8),使用 h2db 进行集成测试是否是一种不好的做法/应该避免。

我不确定我是否同意这一点,因为我们在后端使用 spring boot/hibernate。

我阅读了一些文章,发现这篇文章 https://phauer.com/2017/dont-use-in-memory-databases-tests-h2/ 基本上说明了以下(以及更多):

TL;博士

使用内存数据库进行测试会降低可靠性和 你的测试范围。您的应用程序的 sql 可能会在生产中失败 针对真实数据库,尽管基于 h2 的测试是绿色的。

它们提供与真实数据库不同的功能。可能的 后果是:

  • 您更改应用程序的 sql 代码只是为了使 它运行在真实数据库和内存数据库中。这可能会导致 不太有效、优雅、准确或可维护的实现。要么 你根本无法做某些事情。
  • 您跳过了一些测试 功能齐全。

据我所知,对于一个带有一些业务逻辑的简单 CRUD 应用程序,所有这些点都与我无关(文章中有更多内容),因为 hibernate 包装了所有 sql,并且在代码

有没有我忽略或没有考虑过反对 h2db 的观点?是否有关于使用内存数据库进行 Spring Boot/hibernate 集成测试的“最佳实践”?

解决方法

如果可能,我会避免使用 H2 DB。使用 H2DB 很好,当您无法运行自己的实例时,例如,如果您的公司使用 Oracle 之类的东西,并且不允许您在任何地方(本地机器、自己的开发服务器...)运行自己的数据库。

H2DB 的问题如下:

  1. H2DB 和您的数据库的迁移脚本可能不同。您可能需要对 H2DB 脚本和 MySQL 脚本进行一些调整。

  2. H2DB 通常不提供相同的功能,如真正的 RDBMS,您只使用 SQL 就降低了 DB,您将无法测试存储过程、触发器和所有可能派上用场的花哨的东西。

  3. H2DB 和其他 RDBMS 是不同的。测试不会测试相同的东西,您可能会在生产中遇到一些不会出现在测试中的错误。

说到您的简单 CRUD 应用程序 - 它可能不会永远保持这样。

但是继续使用您喜欢的任何方法,最好自己获得您的个人经验,我经常对 H2DB 感到厌烦。

,

我想说这取决于您的测试范围以及您可以负担得起的集成测试。我更喜欢在尽可能接近我的生产环境的环境中进行测试。但这是理想的情况,实际上由于各种原因,这可能是不可能的。此外,期望 hibernate 完美地抽象出底层细节也是一种理想情况,实际上这种抽象可能会给您一种错误的安全感。

如果您的测试范围只是测试 CRUD 操作,则内​​存中测试应该没问题。它将在该范围内充分发挥作用。它甚至可能有利于减少测试时间以及一定程度的复杂性。它不会检测任何平台/版本/供应商特定问题,但这无论如何都不是测试的范围。在进入生产环境之前,您可以在暂存环境中测试这些内容。

在我看来,现在使用 docker 等工具创建尽可能接近生产环境的测试环境比以往任何时候都容易,CI/CD 工具/平台也支持为此目的启动服务。如果这对您的用例来说不可用或太复杂,那么回退是可以接受的。

根据经验,我在部署到生产环境时遇到了与平台/版本/供应商特定问题相关的失败,尽管我对内存数据库的所有测试都变成了绿色。尽早发现这些问题总是更好,可以节省大量重复开发时间,最重要的是您可以睡个好觉。