Mockito Spy模拟部分方法失效问题求助
嘿,我帮你分析下你遇到的Mockito Spy模拟syncLogs()方法没生效的问题,这几个排查方向你可以逐一试试:
1. 先检查参数匹配是否完全对上
Mockito的方法模拟是认精确参数的,如果测试里模拟用的参数和实际代码调用syncLogs时传的参数不一样,模拟就不会触发,自然会走真实方法。
看你测试里的代码:
Mockito.doReturn(false).when(spy).syncLogs(startTime, endTime, message);
你这里用了自己硬编码的startTime、endTime,还有新建的StringBuilder实例,但manualSyncProess里调用syncLogs时,传的参数可能和这些不一样:
- 比如
startTime和endTime是从args解析出来的,解析过程中会不会有格式调整(比如去掉空格、转成其他格式),导致和你测试里的字符串不匹配? - 再比如
message,你测试里new了一个,但manualSyncProess里是不是自己又new了一个StringBuilder传进去?要是这样,两个对象不一样,参数匹配失败,模拟肯定不生效。
解决办法:
- 如果不需要精确匹配参数,可以用Mockito的参数匹配器来宽松匹配,比如:
Mockito.doReturn(false).when(spy).syncLogs(anyString(), anyString(), any(StringBuilder.class)); - 或者想办法拿到
manualSyncProess里实际用的参数实例,模拟时用完全一样的。
2. 确认Spy实例的创建和使用没毛病
你现在创建Spy的方式是Mockito.spy(ApplicationCmdLine.class),这种方式会用无参构造创建一个Spy实例,但如果ApplicationCmdLine的构造函数需要初始化一些状态,或者你设置的args没作用到这个Spy实例上,可能就会出问题。
更稳妥的做法是先创建真实实例,再包装成Spy:
ApplicationCmdLine app = new ApplicationCmdLine(); // 这里可以先给app设置需要的状态,比如处理args的初始化 ApplicationCmdLine spy = Mockito.spy(app);
另外要确保你调用spy.manualSyncProess(getArgs())时,确实是在操作这个Spy实例,别不小心用到了原始的ApplicationCmdLine对象。
3. 检查方法名有没有笔误
看你贴的ApplicationCmdLine代码里,manualSyncProess里写的是if(!syncLog(.....))——这里是syncLog少了个s,但你模拟的是syncLogs方法!如果这是真实代码里的笔误,那你模拟的方法和实际调用的根本不是同一个,模拟当然不会生效啊!
赶紧核对下真实代码里的方法名,确保和你模拟的完全一致,包括拼写、大小写。
4. 加个验证看看方法到底有没有被调用
你可以在测试里加个验证步骤,确认syncLogs是不是真的被调用了,以及调用时的参数是什么,这样能快速定位问题:
// 在调用spy.manualSyncProess(getArgs())之后加这段 Mockito.verify(spy).syncLogs(anyString(), anyString(), any(StringBuilder.class));
如果验证失败,说明manualSyncProess根本没调用syncLogs;如果验证通过,就再仔细看看参数是不是和你模拟的匹配。
5. 检查syncLogs方法是不是final/static的
如果syncLogs是final或者static方法,Mockito是没法拦截的,因为Spy是基于动态代理实现的,代理不了final/static方法,这种情况下模拟肯定失效。
所以要确保syncLogs是普通的非final、非static方法。
最后再提一句,你说期望syncLogs不执行且返回false,但测试里断言的是spy.manualSyncProess(getArgs())返回true,你得确认下manualSyncProess的逻辑:当syncLogs返回false时,manualSyncProess的返回值到底是true还是false?要是逻辑是syncLogs返回false时manualSyncProess也返回false,那你的断言就写反了,这也会导致测试失败哦。
内容的提问来源于stack exchange,提问作者user2688018

