Mockito:为Spy对象注入Mock,测试A类时Mock其依赖C的D、E
问题背景
现有类结构:
class A { B b; C c; } class C { D d; E e; }
需要为A编写单元测试,要求保留C的真实方法逻辑(不Mock C),但需要Mock C内部的D和E对象。尝试以下三种方案均未生效:
- 方案1:
@Mock B b; @Mock D d; @Mock E e; @Spy @InjectMocks C c; @InjectMocks A a;
- 方案2:
@Mock B b; @Mock D d; @Mock E e; @Spy C c = Mockito.spy(new C(d,e)); @InjectMocks A a;
- 方案3:参考Mockito向Spy对象注入Mock的相关建议
解决方案
方法1:手动注入Mock到Spy实例
先创建C的真实实例,手动注入Mock的D、E后转为Spy,再注入到A中:
@ExtendWith(MockitoExtension.class) public class ATest { @Mock private B b; @Mock private D d; @Mock private E e; private C c; @InjectMocks private A a; @BeforeEach void setUp() { // 初始化C真实实例 c = new C(); // 手动设置Mock的D、E(如果没有setter,用反射) c.setD(d); c.setE(e); // 转为Spy,保留C的真实方法 c = Mockito.spy(c); // 将Spy的C注入A a.setC(c); } @Test void testSample() { // 配置D的Mock行为 when(d.someMethod()).thenReturn("mockedValue"); // 执行A的业务方法 a.execute(); // 验证Mock调用 verify(d).someMethod(); } }
如果C没有公开setter,用反射工具注入:
// 示例:用Mockito的FieldSetter FieldSetter.setField(c, c.getClass().getDeclaredField("d"), d); FieldSetter.setField(c, c.getClass().getDeclaredField("e"), e);
方法2:注解配合初始化修正
用注解时,需确保Mock实例先初始化,再注入到C的Spy中:
@ExtendWith(MockitoExtension.class) public class ATest { @Mock private B b; @Mock private D d; @Mock private E e; @Spy private C c = new C(); @InjectMocks private A a; @BeforeEach void setUp() { // 重新初始化注解,确保Mock就绪 MockitoAnnotations.openMocks(this); // 反射注入D、E到C的Spy FieldSetter.setField(c, c.getClass().getDeclaredField("d"), d); FieldSetter.setField(c, c.getClass().getDeclaredField("e"), e); } // 测试方法... }
失败原因解析
- 方案1:
@Spy与@InjectMocks同用时,Mockito的注入优先级导致D、E的Mock未被注入到C的Spy实例。 - 方案2:初始化
new C(d,e)时,d、e还未被Mockito实例化为Mock(注解初始化有顺序),传入的是null而非有效Mock对象。
内容的提问来源于stack exchange,提问作者deepak gupta
相关产品推荐
相关产品推荐

