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

使用自定义Interceptor时Espresso不等待Mock响应的问题

解决Espresso不等待Mock API加载数据的问题

首先,你的问题根源有两个:FakeInterceptor根本没被实际调用,以及Espresso无法感知RxJava异步任务的完成状态。我们一步步来拆解解决:

1. 修复Repository的Mock配置问题

你当前的Mockito用法存在逻辑误区:你用@Mock创建了一个空的userRepository mock对象,然后试图让它返回mockUserRepository.getUserInfo()的结果,但实际上当测试代码调用userRepository.getUserInfo()时,Mockito会直接返回预设的mock值,根本不会走到mockUserRepository的真实逻辑,自然不会触发FakeInterceptor的intercept方法。

正确的做法是替换掉App中依赖的真实Repository实例,而不是用Mockito mock它。比如通过依赖注入框架或者手动替换:

@Before
public void setUp() {
    appContext = InstrumentationRegistry.getTargetContext();
    
    // 1. 创建带FakeInterceptor的OkHttpClient
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(new FakeInterceptor())
        .build();
    
    // 2. 构建带FakeInterceptor的Retrofit实例
    Retrofit retrofit = new Retrofit.Builder()
        .addConverterFactory(GsonConverterFactory.create(JsonUtils.getInstance().getGson()))
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .baseUrl(Constants.END_POINT)
        .client(okHttpClient)
        .build();
    
    // 3. 创建真实的UserRepository实例,使用上面的Retrofit
    UserRepository mockUserRepository = new UserRepositoryImpl(retrofit); // 替换为你的实际Repository实现类
    
    // 4. 替换App中的Repository依赖(假设Injection类提供静态替换方法)
    Injection.setUserRepository(mockUserRepository);
}

这样当Fragment调用getUserInfo()时,会实际走到带FakeInterceptor的Retrofit请求,触发拦截器逻辑。

2. 让Espresso等待RxJava异步任务完成

Espresso默认只会等待主线程的任务完成,但Retrofit搭配RxJava2CallAdapterFactory时,网络请求是在IO线程执行的,Espresso无法感知这些异步任务。你需要让Espresso能监听RxJava的任务状态,这里有两种实用方案:

方案A:使用RxIdler(推荐)

RxIdler是官方生态的库,能自动将RxJava的Scheduler包装成Espresso可识别的IdlingResource,让Espresso自动等待所有Rx任务完成。

首先添加依赖(在模块的build.gradle的androidTestImplementation块中):

androidTestImplementation 'com.jakewharton.rxidler:rxidler:0.10.0'
androidTestImplementation 'com.jakewharton.rx2idler:rx2idler:0.10.0'

然后在测试的setUp方法中替换RxJava的默认Scheduler:

@Before
public void setUp() {
    // ... 其他初始化代码
    // 替换RxJava的IO和Computation Scheduler为Idler版本
    RxJavaPlugins.setIoSchedulerHandler(Rx2Idler.create("RxJava IO Scheduler"));
    RxJavaPlugins.setComputationSchedulerHandler(Rx2Idler.create("RxJava Computation Scheduler"));
}

方案B:测试中强制RxJava在主线程执行

如果不想引入额外库,可以在测试中让RxJava的所有任务都在主线程执行,这样Espresso就能直接感知并等待:

@Before
public void setUp() {
    // ... 其他初始化代码
    RxJavaPlugins.setIoSchedulerHandler(scheduler -> Schedulers.trampoline());
    RxJavaPlugins.setComputationSchedulerHandler(scheduler -> Schedulers.trampoline());
}

3. (可选)给FakeInterceptor添加延迟模拟真实网络

真实API存在网络延迟,而你的FakeInterceptor是同步立即返回的,可能导致Espresso误以为数据已加载完成(主线程无任务),直接执行下一次点击。可以在拦截器中添加短暂延迟,模拟真实网络情况:

@Override
public Response intercept(Chain chain) throws IOException {
    Response response;
    String responseString = "";
    String requestedPath = chain.request().url().encodedPath();
    
    if (requestedPath.equalsIgnoreCase("api/users/profile/recommendsTab")) {
        responseString = PROFILE__USER_RECOMMENDS;
    } else if (requestedPath.equalsIgnoreCase("api/users/me")) {
        responseString = PROFILE__USER;
    }
    
    // 添加500ms延迟,模拟网络请求耗时
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    
    response = new Response.Builder()
        .code(200)
        .message(responseString)
        .request(chain.request())
        .protocol(Protocol.HTTP_1_0)
        .body(ResponseBody.create(MediaType.parse("application/json"), responseString.getBytes()))
        .addHeader("content-type", "application/json")
        .build();
    return response;
}

4. 调整Espresso测试代码,明确等待UI状态

最后,建议在每次点击后添加UI检查,确保数据加载完成后再执行下一步操作:

// 点击按钮1后,等待推荐列表加载完成
onView(withId(R.id.button_1)).perform(click());
onView(withId(R.id.recycler_recommends)).check(matches(isDisplayed()));

// 点击按钮2后,等待用户信息UI出现
onView(withId(R.id.button_2)).perform(click());
onView(withId(R.id.text_user_name)).check(matches(isDisplayed()));

// 最后点击按钮3
onView(withId(R.id.button_3)).perform(click());

这样Espresso会严格等待指定UI元素加载完成后,再执行后续操作,彻底避免连续点击跳过数据加载的问题。

内容的提问来源于stack exchange,提问作者Tran Hoai Nam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:16:31