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

如何在Mongock集成测试中执行指定范围的change-units

如何在集成测试中执行特定范围的Change Units?

场景说明

现有三个Change Unit:X、Y、Z(order分别设为1、2、3),对应集成测试T1(需仅执行X、Y的迁移)和T2(需仅执行Z的迁移),需要在T1中跳过Z的迁移。

现有方案及不足

你提到的两种方案存在明显弊端:

  • 方案1:将迁移文件按组放入不同包,通过runnerBuilder.addMigrationScanPackage指定扫描包。不足:需要为迁移单独创建包结构,增加不必要的代码分层复杂度。
  • 方案2:使用ChangeUnit#systemVersion,通过setStartSystemVersion和setEndSystemVersion限定范围。不足:SystemVersion设计初衷并非用于测试分组,且需要同步order与systemVersion,维护成本高,容易出错。

替代解决方案

1. 自定义注解+ChangeUnit过滤器

通过给Change Unit添加自定义分组注解,再在测试中通过过滤器筛选目标分组的迁移单元,语义清晰且无额外结构成本。

步骤如下:

  • 定义自定义分组注解:
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface TestMigrationGroup {
        String value(); // 分组标识,比如"t1"、"t2"
    }
    
  • 给目标Change Unit标记注解:
    @TestMigrationGroup("t1")
    @ChangeUnit(order = 1, id = "X")
    public class MigrationX { /* 迁移逻辑 */ }
    
    @TestMigrationGroup("t1")
    @ChangeUnit(order = 2, id = "Y")
    public class MigrationY { /* 迁移逻辑 */ }
    
    @TestMigrationGroup("t2")
    @ChangeUnit(order = 3, id = "Z")
    public class MigrationZ { /* 迁移逻辑 */ }
    
  • 在T1测试中配置过滤器,仅执行t1分组的迁移:
    @Test
    void executeT1Migrations() {
        MigrationRunner runner = MigrationRunnerBuilder.builder()
            .addMigrationScanPackage("com.your.migration.package")
            .changeUnitFilter(changeUnit -> {
                TestMigrationGroup groupAnnotation = changeUnit.getMigrationClass()
                    .getAnnotation(TestMigrationGroup.class);
                return groupAnnotation != null && "t1".equals(groupAnnotation.value());
            })
            .build();
        runner.execute();
    }
    

2. 环境变量/配置驱动的ID筛选

通过外部环境变量或测试配置指定要执行的Change Unit ID,灵活性极高,适合CI/CD场景下动态切换测试范围。

示例实现:

@Test
void executeT1Migrations() {
    // 从环境变量读取要包含的Change Unit ID,也可从测试配置文件读取
    String includedIds = System.getenv("INCLUDE_CHANGE_UNITS");
    Set<String> targetIds = new HashSet<>(Arrays.asList(includedIds.split(",")));

    MigrationRunner runner = MigrationRunnerBuilder.builder()
        .addMigrationScanPackage("com.your.migration.package")
        .changeUnitFilter(changeUnit -> targetIds.contains(changeUnit.getId()))
        .build();
    runner.execute();
}

运行T1测试时,只需设置环境变量INCLUDE_CHANGE_UNITS=X,Y即可;运行T2时设置为INCLUDE_CHANGE_UNITS=Z。

3. 基于Order范围的筛选(适合按顺序分组场景)

如果你的Change Unit已经按order有序排列,可直接在测试中通过过滤器限定order的范围,无需额外注解或配置:

@Test
void executeT1Migrations() {
    MigrationRunner runner = MigrationRunnerBuilder.builder()
        .addMigrationScanPackage("com.your.migration.package")
        .changeUnitFilter(changeUnit -> {
            int order = changeUnit.getOrder();
            return order >= 1 && order <= 2; // 仅执行order为1、2的X、Y
        })
        .build();
    runner.execute();
}

如果是Spring环境,还可以通过@TestPropertySource将范围参数化,进一步提升灵活性:

@TestPropertySource(properties = {"migration.start.order=1", "migration.end.order=2"})
public class T1IntegrationTest {
    @Autowired
    private Environment env;

    @Test
    void runMigrations() {
        int startOrder = Integer.parseInt(env.getProperty("migration.start.order"));
        int endOrder = Integer.parseInt(env.getProperty("migration.end.order"));

        MigrationRunner runner = MigrationRunnerBuilder.builder()
            .addMigrationScanPackage("com.your.migration.package")
            .changeUnitFilter(changeUnit -> 
                changeUnit.getOrder() >= startOrder && changeUnit.getOrder() <= endOrder)
            .build();
        runner.execute();
    }
}

方案对比

方案优势适用场景
自定义注解筛选语义清晰,代码耦合低固定分组的测试场景
环境变量/配置驱动灵活性高,支持动态切换CI/CD流水线、多环境测试
Order范围筛选无需额外代码,利用现有属性Change Unit按顺序明确分组的场景

内容的提问来源于stack exchange,提问作者Filip Kowalski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 01:22:01