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

如何用Android Espresso测试ProgressDialog的显示与消失?

Android Espresso测试:验证ProgressDialog在数据加载完成后消失

推荐方案:使用IdlingResource(官方最佳实践)

Espresso默认仅等待主线程空闲,但后台数据加载(如API请求、Room操作)属于异步任务,不会自动触发Espresso的等待机制。通过注册IdlingResource,可以让Espresso感知异步任务的状态,直到任务完成后再执行断言。

1. 实现自定义IdlingResource

这个资源会监听数据加载的状态,当加载完成时通知Espresso:

public class DataLoadingIdlingResource implements IdlingResource {
    private volatile ResourceCallback callback;
    private boolean isLoading = true;

    @Override
    public String getName() {
        return DataLoadingIdlingResource.class.getName();
    }

    @Override
    public boolean isIdleNow() {
        return !isLoading;
    }

    @Override
    public void registerIdleTransitionCallback(ResourceCallback callback) {
        this.callback = callback;
    }

    // 外部调用此方法更新加载状态
    public void setLoading(boolean loading) {
        this.isLoading = loading;
        if (!loading && callback != null) {
            callback.onTransitionToIdle();
        }
    }
}

2. 在测试类中注册/注销IdlingResource

结合ViewModel(或Repository)的加载状态LiveData,同步IdlingResource的状态:

@RunWith(AndroidJUnit4.class)
public class DataDownloadTest {
    @Rule
    public ActivityScenarioRule<MainActivity> activityRule = new ActivityScenarioRule<>(MainActivity.class);
    
    private DataLoadingIdlingResource idlingResource;

    @Before
    public void setUp() {
        activityRule.getScenario().onActivity(activity -> {
            // 获取ViewModel实例
            MyViewModel viewModel = new ViewModelProvider(activity).get(MyViewModel.class);
            idlingResource = new DataLoadingIdlingResource();
            
            // 观察加载状态,同步到IdlingResource
            viewModel.getIsLoading().observe(activity, isLoading -> {
                idlingResource.setLoading(isLoading);
            });
        });
        
        // 注册到Espresso的空闲资源注册表
        IdlingRegistry.getInstance().register(idlingResource);
    }

    @After
    public void tearDown() {
        if (idlingResource != null) {
            IdlingRegistry.getInstance().unregister(idlingResource);
        }
    }

    @Test
    public void testProgressDialogFlow() {
        // 1. 验证下载按钮可见
        onView(withText("Download data")).check(matches(isDisplayed()));
        
        // 2. 点击下载按钮
        onView(withText("Download data")).perform(click());
        
        // 3. 验证ProgressDialog显示
        onView(withText("Downloading data")).check(matches(isDisplayed()));
        
        // 4. 验证ProgressDialog消失(Espresso会自动等待加载完成)
        onView(withText("Downloading data")).check(matches(not(isDisplayed())));
        // 如果对话框被销毁,也可以用:onView(withText("Downloading data")).check(doesNotExist());
    }
}

备选方案:带超时的等待工具方法

如果暂时无法集成IdlingResource,可以使用带超时的轮询方法替代你的无限循环,避免测试无限挂起:

public static void waitForViewToBeGone(Matcher<View> viewMatcher, long timeoutMillis) {
    long endTime = System.currentTimeMillis() + timeoutMillis;
    
    while (System.currentTimeMillis() < endTime) {
        try {
            onView(viewMatcher).check(matches(not(isDisplayed())));
            return;
        } catch (AssertionError | NoMatchingViewException e) {
            // 视图仍存在,继续等待
            try {
                Thread.sleep(100);
            } catch (InterruptedException ignored) {}
        }
    }
    
    // 超时后抛出断言错误
    onView(viewMatcher).check(matches(not(isDisplayed())));
}

在测试中调用:

// 步骤4:等待对话框消失,超时5秒
waitForViewToBeGone(withText("Downloading data"), 5000);

为什么你的临时方案不推荐

  • 无限循环无超时,若对话框未正常消失,测试会永久挂起
  • 轮询效率低,且不符合Espresso的异步等待设计理念
  • 没有利用Espresso的内置等待机制,容易出现不稳定的测试结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:05:34