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
相关产品推荐
相关产品推荐

