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

JUnit中使用Mockito模拟局部对象失效,求修复方案

问题原因

首先你的原代码存在几处语法错误,先修正(否则无法编译):

  • Public 应为小写的 public(Java关键字大小写敏感)
  • 变量名 Obj 应为 obj(和前面定义的Myclass obj一致)
  • getData(String s1,String s2) 写法错误,调用方法时不需要声明参数类型,应传入实际字符串参数

修正后的原方法示例:

public void method1() {
    Myclass obj = new Myclass();
    Boolean r = obj.getData("s1", "s2");
}

你的mock没生效的核心原因是:测试代码里的obj1和method1内部创建的Myclass实例完全是两个独立对象。method1每次执行都会自己new Myclass(),根本不会用到你在测试里mock出来的对象,所以你定义的when(obj1.getData(...)).thenReturn(...)不会对实际执行产生任何影响。

解决方案

下面提供两种常用修复方式,根据你的场景选择:

方案1:重构代码(推荐,符合面向对象设计原则)

把Myclass对象的创建逻辑抽成单独方法,测试时可以替换这个方法的返回值,让它返回我们的mock对象。

修改原类代码:

public class YourClass { // 假设原方法所在类叫YourClass
    public void method1() {
        Myclass obj = createMyclass(); // 调用抽离的创建方法
        Boolean r = obj.getData("test", "test");
    }

    // 抽离的对象创建方法,默认返回新实例
    protected Myclass createMyclass() {
        return new Myclass();
    }
}

测试代码:

@Test
public void testcase() {
    // 1. 创建原类的spy对象,保留原有逻辑但可替换特定方法
    YourClass yourClassSpy = Mockito.spy(new YourClass());
    // 2. mock Myclass对象并定义行为
    Myclass mockMyclass = Mockito.mock(Myclass.class);
    Mockito.when(mockMyclass.getData("test", "test")).thenReturn(false);
    // 3. 让spy对象的createMyclass方法返回我们的mock对象
    Mockito.doReturn(mockMyclass).when(yourClassSpy).createMyclass();
    
    // 4. 执行测试方法
    yourClassSpy.method1();
    
    // 验证mock方法是否被调用(可选)
    Mockito.verify(mockMyclass).getData("test", "test");
}

方案2:使用PowerMock(不推荐,侵入性强)

如果无法修改原代码,可以用PowerMock拦截new Myclass()的行为,让它返回我们的mock对象。

依赖配置(Maven + JUnit4场景):

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>

测试代码:

// 必须添加这两个注解,告诉PowerMock要拦截的类
@RunWith(PowerMockRunner.class)
@PrepareForTest(YourClass.class) // YourClass是method1所在的类
public class YourClassTest {

    @Test
    public void testcase() throws Exception {
        // 1. mock Myclass对象并定义行为
        Myclass mockMyclass = Mockito.mock(Myclass.class);
        Mockito.when(mockMyclass.getData("test", "test")).thenReturn(false);
        
        // 2. 拦截new Myclass()的行为,返回mock对象
        PowerMockito.whenNew(Myclass.class).withNoArguments().thenReturn(mockMyclass);
        
        // 3. 创建原类实例并执行方法
        YourClass yourClass = new YourClass();
        yourClass.method1();
        
        // 验证方法调用(可选)
        Mockito.verify(mockMyclass).getData("test", "test");
    }
}
注意事项
  • 方案1是更优选择,通过重构让代码更具可测试性,符合面向对象设计原则。
  • PowerMock虽不用改原代码,但会破坏JUnit默认运行机制,升级JUnit或Mockito版本时易出现兼容性问题,尽量避免使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:25:08