
本文深入探讨了junit测试中观察到的类和字段重载现象,解释了其根源在于junit默认的per_method测试实例生命周期。通过介绍@testinstance(lifecycle.per_class)注解,我们展示了如何改变这一行为,同时强调了在使用此注解时需谨慎,以避免违反单元测试的独立性原则,确保测试的健壮性。
在编写JUnit测试时,开发者有时会观察到一个令人困惑的现象:测试类中的final字段,甚至整个测试类实例的哈希码,在不同的测试方法之间会发生变化。这似乎表明测试类在每次测试运行时都被“重新加载”了。例如,在一个测试类中定义一个随机字符串字段,在不同的测试方法中访问时,会发现其值不一致。
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.Test;
class SomeTest {
    // 每次创建实例时都会生成新的随机字符串
    private final String aRandomString = RandomStringUtils.randomAlphabetic(10);
    @Test
    void testMethodA() {
        System.out.println("Method A: " + aRandomString + " (HashCode: " + this.hashCode() + ")");
        // 第一次运行时,aRandomString会有一个值
    }
    @Test
    void testMethodB() {
        System.out.println("Method B: " + aRandomString + " (HashCode: " + this.hashCode() + ")");
        // 第二次运行时,aRandomString会是另一个不同的值
    }
}运行上述代码,会发现testMethodA和testMethodB输出的aRandomString值不同,且this.hashCode()也不同。
这种行为并非偶然,而是JUnit 5(及更高版本)默认测试实例生命周期的设计使然。JUnit 5引入了TestInstance.Lifecycle枚举,它定义了两种主要的测试实例生命周期模式:
PER_METHOD (默认模式):
PER_CLASS:
要改变JUnit的默认行为,使其在整个测试类中只使用一个实例,可以使用@TestInstance注解,并将其Lifecycle参数设置为PER_CLASS:
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class SomeTestPerClass {
    private final String aRandomString = RandomStringUtils.randomAlphabetic(10);
    @Test
    void testMethodA() {
        System.out.println("Method A: " + aRandomString + " (HashCode: " + this.hashCode() + ")");
        // 第一次运行时,aRandomString会有一个值
    }
    @Test
    void testMethodB() {
        System.out.println("Method B: " + aRandomString + " (HashCode: " + this.hashCode() + ")");
        // 第二次运行时,aRandomString的值与Method A相同
    }
}运行SomeTestPerClass,你会发现testMethodA和testMethodB输出的aRandomString值相同,且this.hashCode()也相同。这证明了整个测试类只创建了一个实例。
虽然PER_CLASS模式可以解决字段“重载”的问题,但使用时需要非常谨慎,因为它可能违反单元测试的FIRST原则,特别是独立性(Independent)原则。
对于大多数单元测试,强烈建议坚持使用默认的PER_METHOD生命周期。它确保了每个测试方法都在一个隔离、可预测的环境中运行,从而提高了测试的可靠性和可维护性。只有在明确理解其潜在风险并有充分理由的情况下,才应考虑使用PER_CLASS模式。
JUnit测试中观察到的字段重置和类实例“重载”现象,是由于其默认的PER_METHOD测试实例生命周期所致,即每个测试方法都会获得一个全新的测试类实例。通过使用@TestInstance(TestInstance.Lifecycle.PER_CLASS)注解,可以将生命周期改为PER_CLASS,使所有测试方法共享同一个实例。然而,在采用PER_CLASS模式时,务必权衡其带来的性能优势与可能牺牲的测试独立性,确保测试的健壮性和可维护性。对于大多数单元测试,保持默认的PER_METHOD模式是最佳实践。
以上就是深入理解JUnit测试中的类实例生命周期与字段重置问题的详细内容,更多请关注php中文网其它相关文章!
 
                        
                        每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
 
                 
                                
                                 收藏
收藏
                                                                             
                                
                                 收藏
收藏
                                                                             
                                
                                 收藏
收藏
                                                                            Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号