如何最好地处理带有嵌入式数据库的 Flyway 以进行集成测试?

Posted

技术标签:

【中文标题】如何最好地处理带有嵌入式数据库的 Flyway 以进行集成测试?【英文标题】:How best to handle Flyway with embedded DB for integration tests? 【发布时间】:2015-12-23 12:36:16 【问题描述】:

我有一个现有的应用程序,我最近开始使用 Flyway,并且大部分情况下运行良好。

我一直在为我的开发环境运行一个本地 mysql 数据库,它与 QA 和 Prod 中使用的数据库相匹配。

但是,我希望能够直接针对嵌入式数据库(例如 H2)运行至少一些集成测试。我曾天真地希望,因为 MySQL 似乎(大部分?)将其特殊语句包装在 special comments(例如 /*! SET @foo = 123 */;)中。

但是,当 Flyway 解析我的第一次迁移时,它似乎最终跳过了我的所有 CREATE TABLE 语句,因此它最终只应用了一些参考数据的 INSERT,由于从未创建表而失败。 .

我已尝试调高日志记录级别,但我没有看到任何迹象表明 Flyway 刚刚跳过了我迁移的前 2228 行...

有人对如何最好地处理这种情况有任何建议吗?我尝试在 ENGINE=InnoDB 之类的东西上随意洒一些 /*! ... */ cmets,但似乎 Flyway 仍然跳过这些语句。

我是否最好使用特定于数据库的flyway.locations(如the FAQ 中所述)重新组织和复制大部分(如果不是全部)迁移?或者有什么方法可以让我做最少的更改,至少对我从用于基线迁移的现有数据库的初始mysqldump 得到的更改,以维护两个数据库的单一迁移?

或者...是否有推荐的方法来运行我对 MySQL 的集成测试?我遇到了MySQL Connector/MXJ,但它似乎已经停产了......

【问题讨论】:

【参考方案1】:

这是老问题“没有SQL标准存在”。

Flyway 可能会跳过您的语句,因为它们包含 H2 无法理解的语法。请查看 H2 文档以了解 H2 CREATE TABLE 语法的哪些部分与 MySQL CREATE TABLE 语法不同。如果幸运的话,甚至可能有两个数据库都能理解的语法变体。

否则,您将不得不将 SQL 语句分成两个不同的位置。请记住,您可以同时告诉 Flyway 多个位置。因此,您可以拥有一个通用脚本的核心,并且只移动 db 特定文件中不同的部分。然后,您使用 common + H2 作为位置开始您的本地测试,并使用 common + MySQL 开始您的生产脚本。

如果您使用可以为您创建表的技术(例如 Hibernate),您可能希望在本地执行测试时不使用 Flyway,以避免必须处理两组迁移文件。只需让您的测试生成最新版本的数据库。这也可能具有优势,因为它可能比以后运行大量迁移脚本快得多(比如几年后)。

您必须针对真实的 MySQL 数据库运行一些集成测试,因为您已经看到 H2 的行为可能完全不同。这样,您可能会考虑使用可用于数据库的任何备份解决方案将一些数据侧载到数据库中。这可能比尝试使用 Flyway 从头开始​​初始化数据库要快。 (再次完成您不想在测试之前运行多年的迁移脚本的行。)您可能只想测试最新的脚本集,因为旧的脚本在新的时候确实可以工作(并且 Flyway 将确保它们没有被更改)。

【讨论】:

我喜欢 Hibernate 为我做这件事的想法,但不幸的是,为了让 hibernate 的“验证”模式对我的生产框感到满意,我不得不告诉它我现有的一些列的丑陋细节(例如,它们存储为 MySQL ENUM,不能移植到 H2)。 @pioto 我不建议在 Produktion 甚至在集成测试环境中使用 Hibernate 来生成您的模式。这些 shozld 共享同一个数据库,所以只需使用 Flyway 来设置它们。我建议本地单元测试的 Hibernate 代码生成只是为了避免必须管理两组迁移脚本的工作。当您使用不同的脚本和不同的数据库时,您已经有了一些不具代表性的测试,那么为什么不采用简单的方法呢? 是的,我不认为你是。我只是指出,即使是 Hibernate 生成也可以是特定于 db-vendor 的,当谈到注意特定的列定义时,所以在我的情况下它也不起作用。我认为对我来说最好的解决方案就是多飞行路径迁移路径解决方案。

以上是关于如何最好地处理带有嵌入式数据库的 Flyway 以进行集成测试?的主要内容,如果未能解决你的问题,请参考以下文章

Flyway / Spring和H2嵌入式数据库的架构相关问题

如何将 Flyway 迁移与单个架构和多个项目一起使用

如何在微服务架构中使用 docker-compose 最好地处理共享服务以进行本地开发?

带有 h2 嵌入式数据库的 MySQL LONGTEXT

如何最好地修改带有表前缀的 sql 查询

我如何使用 Flyway,以便如果表被错误地删除,再次运行应用程序时,将创建已删除的表?