Ale*_*x B 17 kotlin rx-java rx-kotlin
我正在尝试测试以下RxKotlin/RxJava 2代码:
validate(data)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap { ... }
Run Code Online (Sandbox Code Playgroud)
我正在尝试覆盖调度程序,如下所示:
// Runs before each test suite
RxJavaPlugins.setInitIoSchedulerHandler { Schedulers.trampoline() }
RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() }
Run Code Online (Sandbox Code Playgroud)
但是,运行测试时出现以下错误:
java.lang.ExceptionInInitializerError
...
Caused by: java.lang.NullPointerException: Scheduler Callable result can't be null
at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39)
at io.reactivex.plugins.RxJavaPlugins.applyRequireNonNull(RxJavaPlugins.java:1317)
at io.reactivex.plugins.RxJavaPlugins.initIoScheduler(RxJavaPlugins.java:306)
at io.reactivex.schedulers.Schedulers.<clinit>(Schedulers.java:84)
Run Code Online (Sandbox Code Playgroud)
有没有人遇到过这个问题?
使用RxKotlin/RxJava 1和以下调度程序覆盖时,测试工作正常:
RxAndroidPlugins.getInstance().registerSchedulersHook(object : RxAndroidSchedulersHook() {
override fun getMainThreadScheduler() = Schedulers.immediate()
})
RxJavaPlugins.getInstance().registerSchedulersHook(object : RxJavaSchedulersHook() {
override fun getIOScheduler() = Schedulers.immediate()
})
Run Code Online (Sandbox Code Playgroud)
谢谢!
Sol*_*dak 24
我建议您采用不同的方法,并为您的调度程序添加一个抽象层.这家伙有一篇很好的文章:https://medium.com/@peter.tackage/an-alternative-to-rxandroidplugins-and-rxjavaplugins-scheduler-injection-9831bbc3dfaf
它在Kotlin看起来像这样
interface SchedulerProvider {
fun ui(): Scheduler
fun computation(): Scheduler
fun trampoline(): Scheduler
fun newThread(): Scheduler
fun io(): Scheduler
}
Run Code Online (Sandbox Code Playgroud)
然后用你自己的SchedulerProvider实现覆盖它:
class AppSchedulerProvider : SchedulerProvider {
override fun ui(): Scheduler {
return AndroidSchedulers.mainThread()
}
override fun computation(): Scheduler {
return Schedulers.computation()
}
override fun trampoline(): Scheduler {
return Schedulers.trampoline()
}
override fun newThread(): Scheduler {
return Schedulers.newThread()
}
override fun io(): Scheduler {
return Schedulers.io()
}
}
Run Code Online (Sandbox Code Playgroud)
还有一个用于测试课程:
class TestSchedulerProvider : SchedulerProvider {
override fun ui(): Scheduler {
return Schedulers.trampoline()
}
override fun computation(): Scheduler {
return Schedulers.trampoline()
}
override fun trampoline(): Scheduler {
return Schedulers.trampoline()
}
override fun newThread(): Scheduler {
return Schedulers.trampoline()
}
override fun io(): Scheduler {
return Schedulers.trampoline()
}
}
Run Code Online (Sandbox Code Playgroud)
你调用RxJava的代码看起来像这样:
mCompositeDisposable.add(mDataManager.getQuote()
.subscribeOn(mSchedulerProvider.io())
.observeOn(mSchedulerProvider.ui())
.subscribe(Consumer<Quote> {
...
Run Code Online (Sandbox Code Playgroud)
您只需SchedulerProvider根据测试位置覆盖您的实现.这是一个示例项目供参考,我链接的测试文件将使用testable:version SchedulerProvider:https://github.com/Obaied/DingerQuotes/blob/master/app/src/test/java/com/obaied/ dingerquotes/QuotePresenterTest.kt#L31
Ale*_*x B 12
弄清楚了!它与此代码中的事实有关:
validate(data)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap { ... }
Run Code Online (Sandbox Code Playgroud)
validate(data)回来了Observable,发出以下几点:emitter.onNext(null).由于RxJava 2不再接受null值,flatMap因此未被调用.我更改validate为返回a Completable并将调度程序覆盖更新为以下内容:
RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
Run Code Online (Sandbox Code Playgroud)
现在测试通过了!
作为提议的解决方案的替代方案,这在我的项目中已经运行良好一段时间了。您可以在测试类中使用它,如下所示:
@get:Rule
val immediateSchedulersRule = ImmediateSchedulersRule()
Run Code Online (Sandbox Code Playgroud)
这个类看起来像这样:
class ImmediateSchedulersRule : ExternalResource() {
val immediateScheduler: Scheduler = object : Scheduler() {
override fun createWorker() = ExecutorScheduler.ExecutorWorker(Executor { it.run() })
// This prevents errors when scheduling a delay
override fun scheduleDirect(run: Runnable, delay: Long, unit: TimeUnit): Disposable {
return super.scheduleDirect(run, 0, unit)
}
}
override fun before() {
RxJavaPlugins.setIoSchedulerHandler { immediateScheduler }
RxJavaPlugins.setComputationSchedulerHandler { immediateScheduler }
RxJavaPlugins.setNewThreadSchedulerHandler { immediateScheduler }
RxAndroidPlugins.setInitMainThreadSchedulerHandler { immediateScheduler }
RxAndroidPlugins.setMainThreadSchedulerHandler { immediateScheduler }
}
override fun after() {
RxJavaPlugins.reset()
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处找到从 TestRule 迁移到ExternalResource 的方法,并在此处获取有关测试 RxJava 2 的更多信息。
这是对我有用的确切语法:
RxJavaPlugins.setIoSchedulerHandler(scheduler -> Schedulers.trampoline())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6257 次 |
| 最近记录: |