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

Mockito @Spy实例反射修改私有字段不生效解决方案咨询

问题根因

反射修改不生效是两个写法问题导致的:

  1. 注解混用错误:你给作为依赖的A实例同时加了@Spy和@InjectMocks,两个注解语义完全冲突。@InjectMocks是用来标记待测试、需要注入依赖的业务类实例的,@Spy是标记作为依赖的Mock对象的,混用后Mockito会把A也当成待测试类处理,可能重新生成A的实例替换你手动new的对象,你后续反射修改的是自己new的旧实例,实际注入到B里的是Mockito新生成的Spy对象,字段自然还是默认值false。
  2. Spy对象是CGLIB动态生成的代理子类实例,如果你反射操作的对象不是最终注入到测试类中的代理实例,修改动作不会作用到实际执行业务逻辑的对象上。
可行方案

首先先修正基础注解配置:删掉A字段上的@InjectMocks,只有待测试的B实例需要保留@InjectMocks注解。修正后的基础测试类结构:

@RunWith(MockitoJUnitRunner.class)
public class BTest {

    @InjectMocks
    private B b;

    @Spy
    private A a = new A();

    // 测试方法
}

在此基础上选以下任意一种方案即可:

方案1:直接存根方法返回值(最稳定,推荐)

不需要反射修改私有字段,直接用Mockito语法存根判断逻辑的返回值,完全绕开字段操作的各种兼容问题:

@Test
public void test() {
    // 注意Spy对象存根必须用doReturn-when语法,不能用when-thenReturn,否则会触发真实方法调用
    doReturn(true).when(a).isUseMethodAEnabled();

    b.funcPrincipal();
    
    // 加验证逻辑确认a()被调用
    verify(a, times(1)).a();
}

方案2:正确反射修改Spy实例字段

确保反射操作的是Mockito生成的最终Spy代理实例,不要操作你手动new的原始对象。如果是集成测试场景下Spy被Spring AOP额外代理,先获取底层目标对象再修改:

@Test
public void test() {
    // 普通单测场景直接修改a即可,此时a已经是Mockito初始化完的Spy实例
    ReflectionTestUtils.setField(a, "isUseMethodAEnabled", true);
    
    // 如果是SpringBootTest等集成测试场景,Spy被AOP代理包裹时用下面的写法
    // A targetA = (A) AopTestUtils.getTargetObject(a);
    // ReflectionTestUtils.setField(targetA, "isUseMethodAEnabled", true);

    b.funcPrincipal();
    verify(a, times(1)).a();
}

方案3:初始化阶段提前设置字段值

把字段修改逻辑放到@Before标注的初始化方法中,确保在Mockito完成所有注入、代理生成动作后,测试方法执行前就把值设置好:

@Before
public void initConfig() {
    ReflectionTestUtils.setField(a, "isUseMethodAEnabled", true);
}

@Test
public void test() {
    b.funcPrincipal();
    verify(a, times(1)).a();
}
避坑提醒
  • 所有作为Mock/Spy依赖的对象,都不要加@InjectMocks注解,否则会出现实例被替换、依赖注入异常、字段修改不生效等各种奇怪问题。
  • 给基本类型(boolean/int/long等)字段反射赋值时,要保证传入的值类型匹配,比如boolean字段要传true/false或者Boolean.TRUE/FALSE,传其他类型值会导致设置静默失败。
  • 给动态代理对象(Spy、Spring AOP对象)做反射操作时,如果修改不生效,优先检查是否需要先获取底层真实目标对象再操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:12:21