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

Java单元测试是否应该全程使用相同的公共变量?

JUnit 单元测试公共资源初始化最佳方案

首先明确:JUnit 默认的测试实例生命周期下,你担心的多线程并发测试变量篡改问题不会出现。

  • JUnit4、JUnit5 默认都会为每一个测试方法单独创建一个测试类的全新实例,@Before(JUnit4)/@BeforeEach(JUnit5)注解的方法会在每个测试方法执行前都运行一次,你在这个方法里给类成员变量赋值,每个测试方法拿到的都是属于自己实例的独立变量,就算多个测试方法并发执行,也不会互相修改对方的变量值。
  • 只有当你主动修改了测试实例生命周期(比如JUnit5加了@TestInstance(Lifecycle.PER_CLASS)注解,整个测试类只生成一个实例),或者用了静态成员变量的时候,才会出现多线程跑测试时变量被篡改的问题,这种场景要避免修改公共资源,或者给资源加线程隔离。

场景1:资源初始化成本低(比如普通列表、简单变量)

直接用@Before/@BeforeEach初始化类成员变量即可,不需要额外处理,这是最常用也最稳妥的方案,既能减少重复代码,也完全没有并发安全问题。
示例代码:

public class MyListTest {
    private List<String> testList;

    @Before
    public void setup() {
        // 每次测试前都生成全新的列表,各测试方法之间完全隔离
        testList = new ArrayList<>(Arrays.asList("a", "b", "c"));
    }

    @Test
    public void testAdd() {
        testList.add("d");
        Assert.assertEquals(4, testList.size());
    }

    @Test
    public void testRemove() {
        testList.remove(0);
        Assert.assertEquals(2, testList.size());
    }
}

场景2:资源初始化成本很高(比如数据库连接、大对象加载)

如果每次测试都重新创建资源开销太大,你可以把资源声明为静态变量,用@BeforeClass(JUnit4)/@BeforeAll(JUnit5)注解的方法只初始化一次,但是要注意:

  • 所有测试方法都不能修改这个公共资源,保证只读
  • 如果必须要修改,可以用ThreadLocal做线程隔离,或者每次修改前对资源做深拷贝

要尽量避免的错误做法:不要在测试类里定义可变的静态变量又不做隔离,很容易出现测试结果不稳定的 flaky 测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 04:54:10