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

测试时覆写RxAndroid调度器:ThreadExecutor的SubscribeOn问题

解决Clean Architecture中UseCase的subscribeOn调度器测试覆写问题

你已经搞定了observeOn的调度器替换,那subscribeOn这边的问题核心是处理Schedulers.from(threadExecutor)生成的Scheduler。我给你分享两种可行的方案,都是围绕让这个Scheduler同步执行任务来实现的:

方案一:Mock ThreadExecutor实现同步执行

假设你的ThreadExecutor是继承自Executor的接口(和那个Android Clean Architecture仓库的定义一致),我们可以通过Mock它的execute方法,让传入的Runnable直接在当前测试线程执行:

// 1. 定义一个直接在当前线程执行任务的Executor
val immediateExecutor = Executor { runnable -> runnable.run() }

// 2. Mock ThreadExecutor实例
val mockThreadExecutor: ThreadExecutor = mock()

// 3. 让mock的execute方法使用我们的同步执行逻辑
whenever(mockThreadExecutor.execute(any())).thenAnswer { invocation ->
    val runnable = invocation.getArgument<Runnable>(0)
    immediateExecutor.execute(runnable)
}

// 4. 将这个mock的ThreadExecutor传入你的UseCase
val useCase = UseCase(testRepo, mockThreadExecutor, testPostExecutionThread)

这样处理后,Schedulers.from(threadExecutor)生成的Scheduler会直接在测试线程同步执行任务,完全符合测试需求,和你替换observeOn调度器的思路保持一致。

方案二:直接使用自定义的同步ThreadExecutor实现

如果你的ThreadExecutor有具体的实现类(比如仓库里的JobExecutor),且允许传入Executor作为构造参数,那你可以直接创建一个同步执行的实例,不需要Mock:

val immediateExecutor = Executor { runnable -> runnable.run() }
val testThreadExecutor = JobExecutor(immediateExecutor) // 假设JobExecutor是你的ThreadExecutor实现类

val useCase = UseCase(testRepo, testThreadExecutor, testPostExecutionThread)

这种方式更直接,适合你不想引入Mock的场景。

为什么这两种方案有效?

Schedulers.from(executor)创建的Scheduler,本质上是把RxJava的任务委托给传入的Executor执行。只要我们让这个Executor的execute方法同步运行Runnable,就相当于把subscribeOn的调度器替换成了同步类型(比如Schedulers.trampoline()或者Schedulers.immediate()),整个UseCase的数据流都会在测试线程按顺序执行,方便你做结果断言。

内容的提问来源于stack exchange,提问作者Chan Myae Aung

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:49:57