在调用层级中插入Mock对象:Mockito单元测试咨询
如何在多层调用链中使用Mockito模拟ClassC.methodC
没问题,我来帮你搞定这个多层依赖的Mock场景!你的调用链是ClassA.methodA() → ClassB.methodB() → ClassC.methodC(),我们需要隔离ClassC的实际逻辑,让它返回预设的模拟值,同时测试上层的调用流程。下面是具体的实现步骤和代码示例:
核心思路
我们需要从最底层的依赖(ClassC)开始Mock,然后把这个Mock对象逐层注入到上层的依赖中,最终让待测试的ClassA实例使用配置好的依赖链,这样就能完全控制ClassC的返回值,而不会执行它的实际逻辑。
代码实现(基础版,适合public字段)
假设你的类字段都是public的(就像你给出的代码结构),可以直接手动注入Mock对象:
import org.junit.jupiter.api.Test; import static org.mockito.Mockito.*; class ClassATest { @Test void testMethodA() { // 1. 创建ClassC的Mock对象 ClassC mockC = mock(ClassC.class); // 2. 预设mockC.methodC()的返回值 Object mockReturnValue = new Object(); // 换成你需要的模拟值 when(mockC.methodC()).thenReturn(mockReturnValue); // 3. 创建ClassB实例,并注入mockC ClassB b = new ClassB(); b.c = mockC; // 4. 创建ClassA实例,并注入配置好的ClassB ClassA a = new ClassA(); a.b = b; // 5. 执行待测试的方法 a.methodA(); // 6. 验证mockC的methodC是否被正确调用(可选,但推荐) verify(mockC).methodC(); } }
更优雅的方式(适合私有字段,使用@InjectMocks)
如果你的ClassB和ClassA中的字段是私有(而非public),可以用Mockito的@InjectMocks和@Mock注解自动完成依赖注入,代码会更简洁:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import static org.mockito.Mockito.*; class ClassATest { // 声明需要Mock的底层依赖 @Mock private ClassC mockC; // 自动将mockC注入到ClassB实例中 @InjectMocks private ClassB b; // 自动将配置好的b注入到ClassA实例中 @InjectMocks private ClassA a; @BeforeEach void setUp() { // 初始化Mockito注解 MockitoAnnotations.openMocks(this); } @Test void testMethodA() { // 预设mockC的返回值 Object mockReturnValue = new Object(); when(mockC.methodC()).thenReturn(mockReturnValue); // 执行测试方法 a.methodA(); // 验证调用行为 verify(mockC).methodC(); } }
关键要点解释
- Mock最底层依赖:我们只需要Mock
ClassC,因为它是实际需要隔离的外部逻辑/依赖,上层的ClassB和ClassA我们用真实实例(或部分Mock,这里用真实实例更适合测试业务流程)。 - 逐层注入:必须确保
ClassB使用的是我们Mock的ClassC,ClassA使用的是配置好的ClassB,这样调用链才能走到Mock对象上。 - 预设返回值:
when(mockC.methodC()).thenReturn(...)告诉Mockito,当methodC被调用时,返回我们指定的模拟值,而不是执行ClassC中的实际逻辑。 - 验证调用:
verify(mockC).methodC()可以确认methodC确实被调用了,保证整个调用链是正常执行的。
内容的提问来源于stack exchange,提问作者lebowski




