JUnit/Mockito无法Mock指定值问题排查求助
嘿,我来帮你搞定这个Mockito的坑!你说黑名单用户测试里,blacklistDeviceService.getBlacklistDeviceForSearch()没返回你指定的deviceListForIp反而返回空列表,导致本该抛出的异常没触发,我给你梳理几个最可能的原因和解决办法:
1. 参数匹配不精准
你用eq()来匹配所有参数,但很可能某个参数的实际值和你mock时传入的不一致,导致Mockito认为这不是同一个调用,就返回默认的空列表了。比如:
- 检查
PropertiesUtil.BlacklistType.IP_ADDRESS.ordinal()的实际数值,是不是和测试时方法调用传入的完全一致? - 测试环境里
request.getRemoteAddr()的返回值是不是你预期的IP?比如本地测试可能是127.0.0.1或者localhost,如果和你mock时用的eq(request.getRemoteAddr())对应的实际值不匹配,就会失效。 - 后面三个
null参数,实际调用时是不是真的传的null?如果实际传的是空字符串或者其他默认值,eq(null)就匹配不上。
解决办法:
先把参数匹配放宽,用any()系列方法测试:
when(blacklistDeviceService.getBlacklistDeviceForSearch(anyInt(), anyString(), anyBoolean(), any(), any(), any())) .thenReturn(deviceListForIp);
如果这样改了之后能返回指定列表,就逐个把any()换回eq(),每次改完跑测试,直到找到哪个参数不匹配,再针对性调整。
2. Mock对象没被正确注入
你得确保blacklistDeviceService是真的被Mockito代理的对象,并且正确注入到了被测试的登录认证组件里。如果被测试类用的是真实的blacklistDeviceService实例,你的mock肯定不会生效。
解决办法:
- 测试类里用
@Mock标注blacklistDeviceService,用@InjectMocks标注被测试的登录认证类; - 测试方法前记得初始化mock对象:要么加
@RunWith(MockitoJUnitRunner.class),要么在@Before方法里调用MockitoAnnotations.openMocks(this)。
3. 方法重载导致mock错了方法
有没有可能blacklistDeviceService有多个重载的getBlacklistDeviceForSearch方法?你mock的方法签名和实际调用的是不是同一个?比如参数类型有没有差异(比如某个参数是Integer而你用了int)?
解决办法:
用Mockito的verify方法验证一下,确认你mock的方法真的被调用了:
verify(blacklistDeviceService).getBlacklistDeviceForSearch(anyInt(), anyString(), anyBoolean(), any(), any(), any());
如果这行代码报错说方法未被调用,说明实际调用的是另一个重载方法,你需要调整mock的方法签名。
4. 指定返回的列表本身是空的
最后别忘了检查deviceListForIp的初始化代码,它是不是真的包含至少一个黑名单设备对象?如果它本身就是空列表,那返回空也是正常的,自然触发不了异常逻辑。
调试小技巧:
在测试方法里打印列表大小确认:
System.out.println("deviceListForIp size: " + deviceListForIp.size());
按照上面的步骤排查,应该能快速找到问题所在!
内容的提问来源于stack exchange,提问作者shadow

