You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单元测试中使用Flyway时如何重置SQLite的AUTOINCREMENT自增序列

问题根因

你之前尝试的方案不生效的核心原因:SQLite的AUTOINCREMENT字段的计数是存储在系统内置表sqlite_sequence中的,Flyway默认的clean操作只会清理用户创建的业务表,不会修改这个系统表的内容,所以即使你删除重建了Tag表,之前的自增计数仍然会被保留,导致新插入数据的ID逐次递增。

可行解决方案
  • 方案1:单元测试改用内存型SQLite(最推荐)

    直接把单元测试环境的数据源配置为内存SQLite,每次测试启动时都会初始化一个全新的数据库实例,不存在任何历史数据残留,自然也不会有自增ID计数继承的问题,不需要额外修改Flyway配置。
    Spring Boot测试配置示例(在src/test/resources/application.properties中添加):

    spring.datasource.url=jdbc:sqlite::memory:
    spring.datasource.driver-class-name=org.sqlite.JDBC
    
  • 方案2:在Flyway迁移脚本中补充重置自增计数逻辑

    如果你必须使用文件型SQLite做测试,可以在创建Tag表的迁移脚本末尾,添加清理sqlite_sequence对应记录的语句,每次建表后直接重置该表的自增起始值:
    你的V1版本迁移脚本修改后如下:

    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
    );
    -- 新增以下语句重置自增计数
    DELETE FROM sqlite_sequence WHERE name='Tag';
    

    该语句执行后,下一条插入Tag表的数据ID会从1开始计数,加上你预填充的2条数据,新增的ID必然为3,符合你的测试预期。

  • 方案3:优化单元测试断言逻辑(最佳实践)

    单元测试硬编码断言自增ID的具体值本身属于不够健壮的写法,你可以调整断言逻辑,避免依赖自增ID的固定值:

    @Test
    public void add() {
        // 先查询当前已有数据的最大ID和条数
        List<Tag> oldTags = this.tagDao.get();
        Long maxIdBefore = oldTags.stream().mapToLong(Tag::getId).max().orElse(0L);
        int sizeBefore = oldTags.size();
    
        Tag tagToAdd = new Tag("Tall");                       
        Tag addedTag = this.tagDao.add(tagToAdd);
        assertNotNull(addedTag);
        // 改成断言ID比之前的最大值大1即可,不需要固定为3
        assertEquals(maxIdBefore + 1, addedTag.getId());              
        assertEquals(tagToAdd.getTag(), addedTag.getTag());   
        List<Tag> tags = this.tagDao.get();
        assertEquals(sizeBefore + 1, tags.size());
    }
    

    这种写法即使后续你调整了预填充数据的条数,测试也不需要同步修改,兼容性更强。

  • 方案4:修正@FlywayTest注解配置

    你之前使用@FlywayTest注解不生效,大概率是没有开启方法级别的清理,默认注解只会在测试类执行前清理一次,如果你单个类下有多个测试方法操作Tag表,就会出现计数累积。你可以修改注解参数,开启每个测试方法执行前都清理数据库:

    @FlywayTest(cleanForEachTest = true)
    public class TagDaoTest {
        // 测试方法
    }
    

    搭配方案2的重置sqlite_sequence的语句,就能保证每次测试的自增计数都是从头开始。

内容的提问来源于stack exchange,提问作者Sandrew Cheru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 08:54:04