为何Mock后目标方法仍会执行?附JUnit测试代码片段
我看了你的测试代码片段,最可能的问题已经浮现出来了,咱们一步步拆解常见原因,帮你定位问题:
1. 局部变量覆盖了成员变量,导致Mock对象没被用上
你在测试类里声明了成员变量 KubernetesClient kubeClient;,但在setup方法里又重新定义了一个同名的局部变量:
// 这里的kubeClient是局部变量,和类成员变量没关系 KubernetesClient kubeClient = Mockito.mock(...);
这就导致类里的成员变量kubeClient根本没被赋值,测试时你用的大概率是真实的KubernetesClient实例(或者被测类里自己创建了真实对象),自然会执行真实方法。
解决办法:去掉局部变量的类型声明,直接给成员变量赋值:
// 直接给类成员变量赋值 kubeClient = Mockito.mock(KubernetesClient.class);
2. Mock对象没有注入到被测类中
如果你的被测类(比如Myclass)里的KubernetesClient是通过new KubernetesClient()这种方式直接创建的,那你在测试类里mock的对象根本和它没关系。被测类还是会用自己new出来的真实实例,Mock自然不起作用。
解决办法:
- 给被测类添加构造函数,把
KubernetesClient作为参数传入:public class Myclass { private KubernetesClient kubeClient; public Myclass(KubernetesClient kubeClient) { this.kubeClient = kubeClient; } // 业务方法... } - 然后在测试的setup方法里,把Mock的kubeClient注入到被测类:
Myclass myClassUnderTest = new Myclass(kubeClient); - 或者用Mockito的
@InjectMocks和@Mock注解配合,自动注入:public class MyclassTest extends JUnitSuite { @Mock KubernetesClient kubeClient; @InjectMocks Myclass myClassUnderTest; @Before public void initMocks() { MockitoAnnotations.openMocks(this); system = ActorSystem.create(); } }
3. 混淆了Mock和Spy的用法
如果你不小心用了Mockito.spy(真实对象)而不是Mockito.mock(类.class),Spy默认会调用真实方法,除非你明确Stub某个方法。如果你想完全替代真实对象的行为,一定要用mock()而不是spy()。
4. Stub的方法签名不匹配
比如你Stub了kubeClient.create(deployment),但实际调用时传入的deployment对象和Stub时的参数不匹配,Mockito会默认返回该类型的默认值(比如null),但如果是Spy对象的话就会走真实方法。要确保Stub的参数和实际调用一致,或者用参数匹配器(比如any(Deployment.class))来匹配:
Mockito.when(kubeClient.create(Mockito.any(Deployment.class))).thenReturn(mockResult);
结合你的代码来看,先检查第一点的局部变量问题,这是最常见的新手坑,解决后再看是否需要调整注入逻辑。
内容的提问来源于stack exchange,提问作者user_mda

