You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Mockito测试Android应用:doThrow方法致测试挂起无结果求助

解决Mockito测试AsyncTask时doThrow挂起的问题

嘿,我碰到过类似的AsyncTask测试坑!你现在遇到的挂起问题,大概率是因为AsyncTask的内部线程机制,加上Mockito spy真实实例时的兼容性问题导致的。咱们一步步来拆解和修复:

1. 别再Spy真实的AsyncTask实例了!

AsyncTask内部维护着自己的线程池和任务状态,直接spy真实的PackageDownloader实例很容易让Mockito的拦截逻辑和AsyncTask的内部运作冲突,导致线程卡住。换个思路,直接mock整个PackageDownloader类:

// 直接mock类,不用搞真实实例的spy
PackageDownloader mockPackageDownloader = Mockito.mock(PackageDownloader.class);
HttpURLConnection connectionMock = Mockito.mock(HttpURLConnection.class);

// 正常模拟createConnection方法
Mockito.doReturn(connectionMock)
       .when(mockPackageDownloader)
       .createConnection(Mockito.any(URL.class));

// 现在再模拟get()抛异常就不会挂起了
Mockito.doThrow(new InterruptedException())
       .when(mockPackageDownloader)
       .get();

2. 检查你的get()方法能不能被Mockito拦截

如果你的PackageDownloader重写了AsyncTask的get()方法,千万别把它写成final的!Mockito默认没法拦截final方法,这会导致你的doThrow完全不生效,进而出现莫名其妙的挂起。如果实在要用final方法,得开启Mockito的inline mock支持,但真心不推荐——尽量让测试方法保持非final。

3. 确认downloadPackage()用的是你mock的实例

这是很多人容易犯的低级错误:你辛辛苦苦mock了实例,结果downloadPackage()内部又new了一个全新的PackageDownloader,那你的mock完全白搭!一定要确保downloadPackage()使用的是你创建的mockPackageDownloader对象,比如通过依赖注入传进去。

4. 妥善处理InterruptedException

InterruptedException是受检异常,测试时要么在测试方法上声明抛出它,要么在内部捕获处理,不然线程可能因为未处理的异常卡住:

@Test(expected = InterruptedException.class)
public void testDownloadPackageThrowsInterruptedException() throws InterruptedException {
    // 先做好mock设置
    // 然后调用downloadPackage()或者直接触发get()
    downloadPackage();
}

额外小建议:换掉AsyncTask吧

AsyncTask早就被Android官方废弃了,它的线程模型在测试时真的麻烦不断。如果项目允许,建议改用Coroutines或者RxJava来实现异步任务,这些框架的测试支持友好得多,Mockito模拟异常也会顺畅很多。


内容的提问来源于stack exchange,提问作者annaoomph

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:27:21