如何使用Mockito对类属性的方法调用执行mock操作?
问题根本原因
你写的测试代码不生效,是因为MyClass构造方法内部直接new了真实的OtherClass实例,myClass.other是普通的真实对象,而非Mockito生成的Mock/Spy对象,Mockito无法拦截真实对象的方法调用,所以打桩逻辑不会生效,会走真实的sendRequest()逻辑。
解法1:重构代码使用依赖注入(最佳实践)
优先调整原类的构造逻辑,把依赖从外部传入,从根源上解决可测试性问题,同时不会破坏原有逻辑的兼容性:
public class MyClass { protected OtherClass other; // 新增依赖注入构造方法,专门用于测试/框架注入 public MyClass(OtherClass other) { this.other = other; } // 保留原有构造方法,保证业务侧使用兼容 public MyClass(String arg) { this.other = new OtherClass(arg); } public void doSomething() { String response = other.sendRequest(); // ... } }
对应的测试代码:
// JUnit5需要加这个注解启用Mockito支持,JUnit4用@RunWith(MockitoJUnitRunner.class) @ExtendWith(MockitoExtension.class) public class MyClassTest { @Mock private OtherClass other; @Test public void doSomethingTest() { // 直接传入Mock对象构造MyClass MyClass myClass = new MyClass(other); when(other.sendRequest()).thenReturn("response"); myClass.doSomething(); // 后续补充你需要的断言逻辑 } }
解法2:不修改原代码,通过反射替换依赖
如果无法改动原MyClass的代码,可以通过反射手动把实例内的other字段替换为Mock对象:
@ExtendWith(MockitoExtension.class) public class MyClassTest { @Test public void doSomethingTest() throws NoSuchFieldException, IllegalAccessException { MyClass myClass = new MyClass("test"); // 构造Mock的OtherClass对象并打桩 OtherClass mockOther = Mockito.mock(OtherClass.class); when(mockOther.sendRequest()).thenReturn("response"); // 反射修改protected字段的值 Field otherField = MyClass.class.getDeclaredField("other"); otherField.setAccessible(true); otherField.set(myClass, mockOther); myClass.doSomething(); // 后续补充你需要的断言逻辑 } }
内容的提问来源于stack exchange,提问作者sininen
相关产品推荐
相关产品推荐

