如何在单元测试中使用 Flyway 时重置 SQLite 自动增量

Posted

技术标签:

【中文标题】如何在单元测试中使用 Flyway 时重置 SQLite 自动增量【英文标题】:How to reset SQLite autoincrement while using Flyway in Unit test 【发布时间】:2021-11-14 12:59:39 【问题描述】:

在单元测试中考虑下面的代码,我在预填充的 SQLite 数据库中添加了一个新的 Tag 对象。

@Test                                                     // Line 1
public void add()                                        
    Tag tagToAdd = new Tag("Tall");                       
    Tag addedTag = this.tagDao.add(tagToAdd);
    assertNotNull(addedTag);
    assertEquals(3L, addedTag.getId());                   // Line 6
    assertEquals(tagToAdd.getTag(), addedTag.getTag());   
    List<Tag> tags = this.tagDao.get();
    assertEquals(3, tags.size());

在第 6 行,我希望标签的 ID 为 3,因为该字段是 AUTOINCREMENT,并且测试是使用已经包含 2 个标签的数据库初始化的。这在我每次运行测试时都可以正常工作,并且 ID 始终为 3。

现在,我正在将 flyway 集成到项目中。每次运行测试,AUTOINCREMENT从上次运行的值开始,所以每次运行Tag ID加1,测试失败。

关于如何让 flyway 始终将数据库重置为全新状态并重置 AUTOINCREMENT 值的任何想法?我可以编写一个查询来手动完成,但这是不可维护的。

到目前为止我尝试了什么?

集成@FlywayTest,因为这会执行flyway task clean 定义了一个FlywayMigrationStrategy bean,其中包含flyway.clean() 在我的 application.properties 中将 spring.flyway.clean-on-validation-error 设置为 true(也就是说,我的 sql 没有变化,所以不确定这是否改变了任何东西)

-- 编辑 我的第一个迁移脚本包含以下内容。

DROP TABLE IF EXISTS Tag;

CREATE TABLE Tag(
    id INTEGER PRIMARY KEY AUTOINCREMENT, 
    tag VARCHAR(255) NOT NULL UNIQUE,
    createdDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    modifiedDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

【问题讨论】:

在每次测试之前重新创建或清理数据库是一种很好的做法,可以确保测试始终以正确的初始状态运行。 flyway.clean() 删除配置模式中的所有对象,因此如果在每次测试执行之前运行它,则每次都应该从空数据库开始。你提到你已经尝试过了。这对你有用吗? 【参考方案1】:

如果我对所有内容的理解都正确 - 您有一个数据库和一个在该数据库中创建一次的表,并且每次都使用同一个表进行测试 - 您只需在测试完成时从表中删除行(而不删除它) (或在开始下一个测试之前)并且每次运行测试时,flyway 都会在此表中插入两个标签。

如果这是正确的 - 您可以在 SQLite 中重置序列以将其设置回1,因此下一个插入的行将使用此id 插入。您可以通过运行以下查询来做到这一点:

UPDATE `sqlite_sequence` SET `seq` = 1 WHERE `name` = 'tags_table_name';

或者,您可以将seq 设置为0 - 此值不正确,因此 SQLite 将使用下一个可用的正确值(如果表中没有行 - 它将是一个,如果有一些值 - 它将第一个可用的号码)。

另一种可能性是在测试后删除您的表并在运行下一个测试之前重新创建它 - 因为它是一个仅用于测试的数据库和表 - 它应该可以正常工作。这样,您每次都将序列计数器设置回值 1。我实际上会这样做,直到您有充分的理由不删除该表为止。

【讨论】:

是的,我想在每次测试之前重新创建和重新填充数据库。但是当我添加飞行路线时,这并没有发生。我已将我的第一个迁移脚本的内容添加到问题中 那么你试过我提供的解决方案了吗?我知道这不是完美的解决方案,但它应该可以解决问题(一种解决方法)。关于正确的解决方案 - 您使用 Spring Boot 还是 Spring(但不是 Sprint Boot)?您能否展示定义了 FlywayMigrationStrategy bean 的配置类?

以上是关于如何在单元测试中使用 Flyway 时重置 SQLite 自动增量的主要内容,如果未能解决你的问题,请参考以下文章

尝试在 sql-server 上迁移时 Flyway 挂起

每次测试单元功能后如何重置数据库?

Flyway迁移无法识别beforeValidate.sql

使用 Flyway 按环境有条件地加载数据

如何在flyway中编辑现有的sql文件

我可以将 Flyway 与 SQL Server 加密一起使用吗?