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

如何让JUnit 5暂停其他线程,单独执行指定测试类?

如何让指定初始化测试类单独执行,其他测试等待其完成?

我原本以为给测试类添加@Execution(ExecutionMode.SAME_THREAD)注解就能让它单独执行,但实际没生效——其他测试类还是会和它并行运行。我需要实现的是:让所有其他测试都等待AaInitialStateITCase执行完成后再启动,比如现在设置forkCount = 4时,实际执行顺序是混着的:

  1. 运行pl.mol.molnet.initsaas.Dummy2ITCase
  2. 运行pl.mol.molnet.initsaas.Dummy1ITCase
  3. 运行pl.mol.molnet.initsaas.AaInitialStateITCase
  4. 运行pl.mol.molnet.initsaas.Dummy3ITCase
  5. Dummy1ITCase测试完成,耗时27.68秒
  6. 运行pl.mol.molnet.initsaas.Dummy4ITCase
  7. Dummy4ITCase测试完成,耗时0.008秒

本质上我希望初始化类这类特殊测试能先单独执行,其他测试再并行启动。


示例测试类

/**
 * 初始化主数据库对象。
 * @author Maciej Nux Jaros
 */
@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/testContextPg.xml"})
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Execution(ExecutionMode.SAME_THREAD)   // 不能并行执行
public class AaInitialStateITCase extends TestDatabaseCleaner {
    @BeforeAll
    public void mockTenantService() throws SaasException {
        initAll();
    }

    @Test
    public void testInit_shouldInitTenants() throws Exception {
        assertNotNull(tenant1);
        assertNotNull(tenant2);
    }
}

/**
 * 用于占用线程的测试类。
 * @author Maciej Nux Jaros
 */
@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/testContextPg.xml"})
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class Dummy1ITCase extends TestDatabaseCleaner {
    @Test
    public void test_forthreads() throws Exception {
        assertEquals(2, 1+1);
    }
}

Maven配置

<!-- ITCase 配置 -->
<plugin>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>${maven.surefire-failsafe.plugin.version}</version>
    <executions>
        <execution>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <skipTests>${skip.integration.tests}</skipTests>
        <forkCount>4</forkCount>
        <reuseForks>true</reuseForks>
        <argLine>-Xms512m -Xmx1280m -Dfile.encoding=UTF-8</argLine>
        <properties>
            <configurationParameters>
                junit.jupiter.execution.parallel.enabled = true
                junit.jupiter.execution.parallel.mode.default = concurrent
                junit.jupiter.execution.parallel.mode.classes.default = same_thread
                # 按类名排序以安全初始化数据库
                junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$ClassName
            </configurationParameters>
        </properties>
    </configuration>
</plugin>

解决方案

问题根源

你当前配置中的forkCount=4意味着Maven会启动4个独立的JVM进程并行执行测试。而JUnit的@Execution注解仅能控制单个JVM进程内的测试线程,跨进程的测试无法通过该注解同步,所以初始化类和其他测试会在不同进程中同时运行。

可行方案

1. 分阶段执行测试

通过Maven Failsafe插件的多执行阶段,先单独运行初始化测试类,再执行其他测试:

<plugin>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>${maven.surefire-failsafe.plugin.version}</version>
    <executions>
        <!-- 第一阶段:单进程执行初始化测试 -->
        <execution>
            <id>run-init-tests</id>
            <goals>
                <goal>integration-test</goal>
            </goals>
            <configuration>
                <forkCount>1</forkCount>
                <includes>
                    <include>**/AaInitialStateITCase.java</include>
                </includes>
            </configuration>
        </execution>
        <!-- 第二阶段:多进程执行其他测试 -->
        <execution>
            <id>run-other-tests</id>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
            <configuration>
                <forkCount>4</forkCount>
                <excludes>
                    <exclude>**/AaInitialStateITCase.java</exclude>
                </excludes>
            </configuration>
        </execution>
    </executions>
    <configuration>
        <skipTests>${skip.integration.tests}</skipTests>
        <reuseForks>true</reuseForks>
        <argLine>-Xms512m -Xmx1280m -Dfile.encoding=UTF-8</argLine>
        <properties>
            <configurationParameters>
                junit.jupiter.execution.parallel.enabled = true
                junit.jupiter.execution.parallel.mode.default = concurrent
                junit.jupiter.execution.parallel.mode.classes.default = same_thread
                junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$ClassName
            </configurationParameters>
        </properties>
    </configuration>
</plugin>

该配置会先以单进程完成AaInitialStateITCase的执行,再启动4个进程并行执行其余测试。

2. 改用JUnit线程级并行

将forkCount设为1,完全依赖JUnit的线程级并行控制执行顺序,此时@Execution和类排序配置会生效:

<forkCount>1</forkCount>

JUnit会在单个进程内按类名排序(你已配置ClassOrderer$ClassName),优先执行AaInitialStateITCase(类名以Aa开头,排序最靠前),且因为加了@Execution(ExecutionMode.SAME_THREAD),它会在单线程执行,其他测试类会在它完成后再按配置的并行模式启动。

3. 使用测试标签分组

给初始化类添加自定义标签,分阶段执行标签组:
在测试类上添加标签:

@Tag("init")
@Execution(ExecutionMode.SAME_THREAD)
public class AaInitialStateITCase extends TestDatabaseCleaner {
    // ...
}

修改Maven配置的执行阶段:

<executions>
    <execution>
        <id>run-init-tests</id>
        <goals>
            <goal>integration-test</goal>
        </goals>
        <configuration>
            <forkCount>1</forkCount>
            <groups>init</groups>
        </configuration>
    </execution>
    <execution>
        <id>run-other-tests</id>
        <goals>
            <goal>integration-test</goal>
            <goal>verify</goal>
        </goals>
        <configuration>
            <forkCount>4</forkCount>
            <excludedGroups>init</excludedGroups>
        </configuration>
    </execution>
</executions>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:44:51