Mockito监视AsyncTask失效:无法Stub HttpURLConnection返回Mock对象
看起来你遇到的是Mockito Spy存根方法没生效的典型问题,我帮你梳理几个可能的原因和对应的解决办法:
1. 先确认方法的可Mock性
首先检查createConnection方法是不是final、static或者private的——Mockito没办法拦截这些类型的方法。从你贴的代码看它是public非final的,这条应该没问题,但还是建议再核对一遍类的完整代码。
2. 检查参数匹配是否精准
你用了Mockito.any(URL.class)来匹配方法参数,但要注意:doInBackground里是通过new URL(downloadUrlString)生成的downloadUrl,哪怕逻辑上和你传入的URL是同一个地址,URL对象的equals比较会校验完整的地址、端口等信息,如果有细微差异(比如一个末尾带斜杠一个不带),参数匹配就会失败,Mockito就会默认调用真实方法。
可以先把参数匹配放宽来测试:
doReturn(connectionMock).when(mPackageDownloader).createConnection(Mockito.any());
如果这样能生效,再回头排查URL对象的匹配细节问题。
3. 确保Spy对象的操作顺序正确
你的代码顺序是对的,但要注意:不要在Spy创建之后再调用setParameters,否则可能会重置实例状态,导致之前的存根失效。确保所有配置操作都在Spy包装实例前完成。
另外可以在execute()之前手动调用一次createConnection,验证存根本身是否生效:
// 在execute前加这行测试 HttpURLConnection testConn = mPackageDownloader.createConnection(new URL(downloadUrlString)); System.out.println(testConn == connectionMock); // 正常应该输出true
如果这行输出true,说明存根是有效的,问题出在doInBackground里的downloadUrlString是否被修改过,或者传入的参数和实际使用的不一致。
4. 改用Mock而非Spy的备选方案
如果Spy的方式始终有问题,可以尝试直接Mock PackageDownloader类,跳过真实实例的依赖:
PackageDownloader mPackageDownloader = Mockito.mock(PackageDownloader.class); // 存根setParameters方法避免空指针 doNothing().when(mPackageDownloader).setParameters(Mockito.any(), Mockito.any(), Mockito.any()); // 存根createConnection返回Mock对象 doReturn(connectionMock).when(mPackageDownloader).createConnection(Mockito.any(URL.class)); // 让Mockito执行真实的doInBackground逻辑 when(mPackageDownloader.doInBackground(Mockito.any())).thenCallRealMethod(); // 执行测试 mPackageDownloader.execute(); mPackageDownloader.get();
这种方式更适合单元测试场景,能彻底隔离真实依赖。
最后排查点
如果以上方法都没用,检查你的Mockito版本是否过旧,建议升级到最新稳定版,旧版本对Spy的处理可能存在兼容性bug。
内容的提问来源于stack exchange,提问作者annaoomph

