如何在JUnit 5测试类中访问被测类的私有静态常量?
在JUnit 5测试用例中访问被测类的private static final常量
我明白你现在的困扰——想在JUnit测试里用MyClass里的private static final常量,但直接访问不了对吧?给你几个可行的办法,从最推荐到不那么推荐排序:
推荐方案:添加公共静态Getter方法
这是最符合面向对象封装原则的做法,既不会破坏被测类的封装性,又能让测试代码安全地获取常量值:
在MyClass中添加一个public的静态方法来暴露常量:
public class MyClass { private static final int HSIZE = 7; private static final int NUM_LOCS = 3; // 新增的公共Getter方法 public static int getNumLocs() { return NUM_LOCS; } // 原有方法... void generateRandomLocations() { Random rand = new Random(); String[] hPos = new String[NUM_LOCS]; for (int i=0; i<NUM_LOCS; i++) { hPos[i] = Integer.toString(rand.nextInt(HSIZE)); } setLocations(hPos); } }
之后在测试用例里直接调用这个方法即可:
@Test void testGenerateRandomLocations() { MyClass mc = new MyClass(); mc.generateRandomLocations(); String[] check = mc.getLocations(); assertEquals(MyClass.getNumLocs(), check.length); }
这种方式的好处是:如果后续NUM_LOCS的值发生变化,测试代码不需要修改,完全依赖被测类的暴露接口,维护性极强。
备选方案:使用反射(仅当无法修改被测类时)
如果你因为某些原因不能修改MyClass的源码(比如是第三方库类),可以通过Java反射机制来访问private static final字段:
import java.lang.reflect.Field; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @Test void testGenerateRandomLocations() throws NoSuchFieldException, IllegalAccessException { MyClass mc = new MyClass(); mc.generateRandomLocations(); String[] check = mc.getLocations(); // 获取NUM_LOCS字段 Field numLocsField = MyClass.class.getDeclaredField("NUM_LOCS"); // 开启访问权限 numLocsField.setAccessible(true); // static字段的get方法传入null即可 int numLocs = (int) numLocsField.get(null); assertEquals(numLocs, check.length); }
⚠️ 注意:反射会破坏类的封装性,而且如果后续被测类中字段名(比如NUM_LOCS)被修改,测试代码会直接抛出NoSuchFieldException,维护成本较高,所以仅作为不得已时的备选方案。
不推荐方案:在测试类中复制常量值
你可能会想到直接在测试类里写死3来代替NUM_LOCS,比如:
assertEquals(3, check.length);
但这种方式非常不推荐——一旦MyClass中的NUM_LOCS值发生变化,你必须手动同步修改测试代码中的数值,很容易因为遗漏导致测试失效,维护性极差。
内容的提问来源于stack exchange,提问作者michjnich
相关产品推荐
相关产品推荐

