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

Mockito.doNothing调用真实方法:层级调用下doNothing不生效如何解决

问题根因

两个核心原因导致doNothing不生效:

  1. 你生成的spy代理对象没有替换A实例内部持有的原始B对象。spy(a.b)会基于原始B实例生成一个新的代理对象,你对这个代理对象的打桩逻辑只作用于代理本身,而a内部的b成员仍然指向原始B实例,调用a.methodA()时走的是原始对象的逻辑,自然不会触发你给代理对象设置的桩规则。
  2. 代码存在拼写错误:你打桩时写的是somethod(),但实际B类的方法是someMethod()(首字母大写),方法名不匹配的情况下Mockito不会识别到对应的桩规则,默认会执行原方法。
解决方案

按优先级给出可落地的修复方式:

  • 方案1:直接替换A实例的b成员(适合当前b为public的场景)
    修复后的测试代码如下:
    A a = new A();
    // 生成spy代理对象
    B bSpy = Mockito.spy(a.b);
    // 注意方法名拼写和原方法完全一致
    Mockito.doNothing().when(bSpy).someMethod();
    // 把a内部的b替换为代理对象
    a.b = bSpy;
    // 此时调用就会触发doNothing规则
    a.methodA();
    
  • 方案2:改造A类为依赖注入模式(更符合可测试性设计的最优方案)
    不要在A的构造函数内部实例化B,而是通过构造参数传入B实例,测试时直接传入spy后的B对象即可:
    // 改造后的A类
    class A {
        public B b;
        // 依赖注入构造函数
        A(B b){
            this.b = b;
        }
        void methodA(){
            b.method1();
        }
    }
    
    // 测试代码
    B bSpy = Mockito.spy(new B());
    Mockito.doNothing().when(bSpy).someMethod();
    A a = new A(bSpy);
    a.methodA();
    
  • 方案3:如果A的b成员是private无法直接赋值,可以通过反射注入spy对象替换原始成员。
注意事项
  • Mockito的代理逻辑只作用于spy/mock生成的代理对象本身,不会修改原始对象的行为,必须保证业务调用链中实际使用的是代理对象,桩规则才会生效
  • 打桩时方法名、参数类型、参数数量必须和目标方法完全一致,否则桩规则不会匹配,默认执行原方法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 06:24:02