Spring中@Value注入的组件JUnit测试调用ReflectionTestUtils报错如何解决
错误根因
抛出java.lang.IllegalArgumentException: Either targetObject or targetClass for the field must be specified的核心原因是你传入ReflectionTestUtils.setField的第一个参数expandQueryParam为null,工具类无法定位要操作的目标对象。
导致实例为null的常见原因有两个:
- 你为同一个
ExpandParam实例同时添加了@Spy和@InjectMocks注解,两个注解作用冲突,Mockito无法正确生成并初始化实例 - 测试类没有添加Mockito对应的运行/扩展注解(JUnit4用
@RunWith(MockitoJUnitRunner.class)、JUnit5用@ExtendWith(MockitoExtension.class)),Mockito注解未生效,实例没有被赋值
解决方案
你可以根据测试场景选择以下两种方案:
方案1:纯单元测试(无需加载Spring上下文,执行速度快)
不需要依赖Spring注入,直接手动赋值私有字段即可:
- 移除
ExpandParam实例上冲突的@Spy、@InjectMocks注解,直接初始化对象 - 调整后测试代码示例如下:
// JUnit5 示例 public class ExpandParamTest { // 直接实例化测试类 private final ExpandParam expandParam = new ExpandParam(); @BeforeEach void setup() { // 此时expandParam为非空,反射赋值不会报错 ReflectionTestUtils.setField(expandParam, "expandParam", "expand"); } @Test void testGetExpandQueryParam() { // 你的测试逻辑 MultiValueMap<String, String> result = expandParam.getExpandQueryParam(new String[]{"field1", "field2"}); // 断言结果符合预期 } }
方案2:Spring环境测试(自动读取配置文件赋值)
如果你需要验证@Value注解读取配置的逻辑是否正确,可以用SpringBoot测试框架,无需手动反射赋值:
@SpringBootTest public class ExpandParamTest { // Spring会自动初始化Bean并注入@Value配置 @Autowired private ExpandParam expandParam; @Test void testGetExpandQueryParam() { // 直接执行测试逻辑即可 } }
补充注意点
- 如果需要使用Mockito相关注解,确保测试类添加了对应的扩展/运行器注解,保证注解生效
- 调用
ReflectionTestUtils前可以先校验目标对象非空,提前定位实例初始化问题
内容的提问来源于stack exchange,提问作者Masoom Raza
相关产品推荐
相关产品推荐

