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

BasicRobot.robotWithCurrentAwtHierarchy()多测试执行时无限冻结问题求助

问题:批量运行FEST Swing测试时无限冻结,单独运行正常

单独运行每个测试用例都能成功,但通过mvn test批量运行所有测试时,后执行的测试会无限冻结。注释掉任意一个测试类中初始化Robot的代码后,mvn test就能正常完成,该问题在IDEA和Maven CLI中均会出现。

相关测试代码

测试类1:

import org.fest.swing.core.BasicRobot;
import org.fest.swing.core.Robot;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class RobotTest {

    static Robot robot;

    @BeforeAll
    static void beforeAll() {
        robot = BasicRobot.robotWithCurrentAwtHierarchy();
    }

    @Test
    void method_ifSomething_thenShouldDoSomething() {
        // no actual test
    }
}

测试类2:

// identical imports

class RobotTest2 {

    // identical content
}

依赖配置

<dependency>
    <groupId>org.easytesting</groupId>
    <artifactId>fest-swing</artifactId>
    <version>1.2.1</version>
</dependency>

问题原因

  • FEST Swing的BasicRobot依赖AWT事件分发线程(EDT)工作,它会独占该线程资源。Maven批量测试默认在同一个JVM进程中执行所有测试,第一个测试类初始化的Robot会占用EDT,后续测试类尝试创建新Robot实例时,会因等待EDT资源陷入死锁,导致无限冻结。
  • 每个测试类的@BeforeAll是静态方法,都会执行一次BasicRobot.robotWithCurrentAwtHierarchy(),多次创建Robot实例会引发EDT的资源冲突。

解决办法

方法1:全局共享一个Robot实例

所有测试类共用同一个Robot实例,避免重复创建。可以编写一个测试基类统一管理:

import org.fest.swing.core.BasicRobot;
import org.fest.swing.core.Robot;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;

public abstract class BaseSwingTest {
    protected static Robot robot;

    @BeforeAll
    static void setupGlobalRobot() {
        if (robot == null) {
            robot = BasicRobot.robotWithCurrentAwtHierarchy();
        }
    }

    @AfterAll
    static void teardownGlobalRobot() {
        if (robot != null) {
            robot.cleanUp();
            robot = null;
        }
    }
}

然后让测试类继承该基类:

import org.junit.jupiter.api.Test;

class RobotTest extends BaseSwingTest {
    @Test
    void method_ifSomething_thenShouldDoSomething() {
        // 测试逻辑
    }
}

class RobotTest2 extends BaseSwingTest {
    @Test
    void anotherTest() {
        // 测试逻辑
    }
}

方法2:每个测试类执行后销毁Robot

在每个测试类的@AfterAll方法中销毁Robot实例,及时释放EDT资源:

import org.fest.swing.core.BasicRobot;
import org.fest.swing.core.Robot;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class RobotTest {
    static Robot robot;

    @BeforeAll
    static void beforeAll() {
        robot = BasicRobot.robotWithCurrentAwtHierarchy();
    }

    @AfterAll
    static void afterAll() {
        if (robot != null) {
            robot.cleanUp();
        }
    }

    @Test
    void method_ifSomething_thenShouldDoSomething() {
        // 测试逻辑
    }
}

RobotTest2做同样修改,确保每个测试类执行完毕后释放资源。

方法3:让每个测试类在独立JVM运行

修改Maven Surefire插件配置,让每个测试类在单独的JVM进程中执行,彻底避免资源冲突:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.2.5</version>
            <configuration>
                <forkCount>1</forkCount>
                <reuseForks>false</reuseForks>
            </configuration>
        </plugin>
    </plugins>
</build>

该方法会增加测试总耗时,但能彻底解决跨测试类的资源竞争问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 19:20:02