JUnit测试中如何复用对象?使用@BeforeAll初始化静态对象报空指针如何解决
问题原因
空指针异常的核心原因是@BeforeAll注解的初始化方法未满足JUnit的执行规则,导致方法根本没有触发运行,d1、d2、d3三个静态变量始终为null,调用equals方法时就会抛出空指针。
解决方案
根据你使用的JUnit版本选择对应修改方式即可实现对象复用:
方案1:JUnit 5 默认规则适配(推荐)
JUnit 5 中@BeforeAll默认要求修饰的方法必须是静态,只需要给你的setup方法增加static修饰符即可,修改后代码如下:
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class MyTests { static Date d1, d2, d3; @BeforeAll public static void setup() { d1 = new Date(7, 11, 2021); d2 = new Date(7, 11, 2021); d3 = new Date(1, 11, 1990); } @Test public void testDateEquals() { assertTrue(d1.equals(d2)); assertFalse(d2.equals(d3)); } }
方案2:JUnit 5 单实例生命周期适配
如果不想使用静态方法,可以给测试类添加@TestInstance(TestInstance.Lifecycle.PER_CLASS)注解,此时JUnit会为所有测试方法共用同一个测试类实例,@BeforeAll可以修饰非静态方法,变量也可以不用static修饰:
import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class MyTests { Date d1, d2, d3; @BeforeAll public void setup() { d1 = new Date(7, 11, 2021); d2 = new Date(7, 11, 2021); d3 = new Date(1, 11, 1990); } @Test public void testDateEquals() { assertTrue(d1.equals(d2)); assertFalse(d2.equals(d3)); } }
方案3:JUnit 4 适配
如果你使用的是JUnit 4,没有@BeforeAll注解,对应的全局初始化注解为@BeforeClass,同样要求修饰静态方法,修改后代码如下:
import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; public class MyTests { static Date d1, d2, d3; @BeforeClass public static void setup() { d1 = new Date(7, 11, 2021); d2 = new Date(7, 11, 2021); d3 = new Date(1, 11, 1990); } @Test public void testDateEquals() { assertTrue(d1.equals(d2)); assertFalse(d2.equals(d3)); } }
注意:如果你的
Date类是可变对象,在测试中会修改对象属性,建议使用@BeforeEach注解替换@BeforeAll,每个测试方法运行前都会重新初始化对象,避免不同测试之间互相干扰。
内容的提问来源于stack exchange,提问作者Chris Eckert
相关产品推荐
相关产品推荐

