J'essaie de tester le code RxKotlin/RxJava 2 suivant:
validate(data)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap { ... }
J'essaie de remplacer les planificateurs comme suit:
// Runs before each test suite
RxJavaPlugins.setInitIoSchedulerHandler { Schedulers.trampoline() }
RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() }
Cependant, le message d'erreur suivant s'affiche lors de l'exécution du test:
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)
Quelqu'un a-t-il eu ce problème?
Le test a fonctionné correctement avec RxKotlin/RxJava 1 et les remplacements de planificateur suivants:
RxAndroidPlugins.getInstance().registerSchedulersHook(object : RxAndroidSchedulersHook() {
override fun getMainThreadScheduler() = Schedulers.immediate()
})
RxJavaPlugins.getInstance().registerSchedulersHook(object : RxJavaSchedulersHook() {
override fun getIOScheduler() = Schedulers.immediate()
})
Merci!
Je vous suggère d’adopter une approche différente et d’ajouter une couche d’abstraction à vos planificateurs. Ce mec a un bel article à ce sujet: https://medium.com/@peter.tackage/an-alternative-to-rxandroidplugins-and-rxjavaplugins-scheduler-injection-9831bbccdfdf
Cela ressemblerait à quelque chose comme ça à Kotlin
interface SchedulerProvider {
fun ui(): Scheduler
fun computation(): Scheduler
fun trampoline(): Scheduler
fun newThread(): Scheduler
fun io(): Scheduler }
Et ensuite, vous remplacez cela par votre propre implémentation de 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()
}
}
Et un pour tester les cours:
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()
}
}
Votre code ressemblerait à ceci lorsque vous appelez RxJava:
mCompositeDisposable.add(mDataManager.getQuote()
.subscribeOn(mSchedulerProvider.io())
.observeOn(mSchedulerProvider.ui())
.subscribe(Consumer<Quote> {
...
Et vous allez simplement annuler votre implémentation de SchedulerProvider
en fonction de l'endroit où vous l'avez testée. Voici un exemple de projet à titre de référence. Je relie le fichier de test qui utiliserait la version testable de SchedulerProvider
: https://github.com/Obaied/DingerQuotes/blob/master/app/src/test/Java/com /obaied/dingerquotes/QuotePresenterTest.kt#L31
Deviner! Cela avait à voir avec le fait que dans ce code:
validate(data)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap { ... }
validate(data)
retournait une Observable
, qui émettait ce qui suit: emitter.onNext(null)
. Puisque RxJava 2 n'accepte plus les valeurs null
, flatMap
n'a pas été appelé. J'ai changé validate
pour renvoyer Completable
et mis à jour le remplacement du planificateur comme suit:
RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
Maintenant les tests sont réussis!