Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HandlerScheduler throws NPE on schedule() in tests #567

Closed
AnastasiaRainMaker opened this issue Apr 20, 2020 · 4 comments
Closed

HandlerScheduler throws NPE on schedule() in tests #567

AnastasiaRainMaker opened this issue Apr 20, 2020 · 4 comments

Comments

@AnastasiaRainMaker
Copy link

Experiencing NPE when running tests in a batch. When running tests in one class or one by one they pass. They used to pass it a batch too a couple of days ago. The only dependency that changed is Gradle plugin upgrade to 3.6.

RXJava version 2.1.1
Sample test:

   interactor.filterAndSaveStoreList(getMockStoreList()).test()
   verify(repository).updateStoresRoom(storeListCaptor.capture())
   //expecting 1 as one store will be filtered out
   assertEquals(1, storeListCaptor.value?.size)

The test() subscription triggers HandlerScheduler schedule() and it hits NPE in line 81. (message.obj = this;)

here is the complete log

java.lang.NullPointerException
	at io.reactivex.android.schedulers.HandlerScheduler$HandlerWorker.schedule(HandlerScheduler.java:81)
	at io.reactivex.Scheduler$Worker.schedule(Scheduler.java:371)
	at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.schedule(ObservableObserveOn.java:161)
	at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.onNext(ObservableObserveOn.java:119)
	at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:58)
	at io.reactivex.internal.operators.mixed.MaybeFlatMapObservable$FlatMapObserver.onNext(MaybeFlatMapObservable.java:69)
	at io.reactivex.internal.operators.observable.ObservableScalarXMap$ScalarDisposable.run(ObservableScalarXMap.java:248)
	at io.reactivex.internal.operators.observable.ObservableJust.subscribeActual(ObservableJust.java:35)
	at io.reactivex.Observable.subscribe(Observable.java:12267)
	at io.reactivex.internal.operators.mixed.MaybeFlatMapObservable$FlatMapObserver.onSuccess(MaybeFlatMapObservable.java:109)
	at io.reactivex.internal.operators.maybe.MaybeSwitchIfEmpty$SwitchIfEmptyMaybeObserver.onSuccess(MaybeSwitchIfEmpty.java:75)
	at io.reactivex.internal.operators.maybe.MaybeJust.subscribeActual(MaybeJust.java:36)
	at io.reactivex.Maybe.subscribe(Maybe.java:4290)
	at io.reactivex.internal.operators.maybe.MaybeSwitchIfEmpty.subscribeActual(MaybeSwitchIfEmpty.java:38)
	at io.reactivex.Maybe.subscribe(Maybe.java:4290)
	at io.reactivex.internal.operators.mixed.MaybeFlatMapObservable.subscribeActual(MaybeFlatMapObservable.java:49)
	at io.reactivex.Observable.subscribe(Observable.java:12267)
	at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
	at io.reactivex.internal.schedulers.TrampolineScheduler.scheduleDirect(TrampolineScheduler.java:52)
	at io.reactivex.internal.operators.observable.ObservableSubscribeOn.subscribeActual(ObservableSubscribeOn.java:36)
	at io.reactivex.Observable.subscribe(Observable.java:12267)
	at io.reactivex.internal.operators.observable.ObservableObserveOn.subscribeActual(ObservableObserveOn.java:45)
	at io.reactivex.Observable.subscribe(Observable.java:12267)
	at io.reactivex.Observable.test(Observable.java:15464)
	at com.heb.sng.ui.location.LocationInteractorTest.test checkForStoreExit returns false if user is in geofence(LocationInteractorTest.kt:163)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:46)
	at com.heb.sng.ui.history.RxImmediateSchedulerRule$apply$1.evaluate(RxImmediateSchedulerRule.kt:27)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:77)
	at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:83)
	at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
	at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)

I am also replacing all my schedulers with a test rule like so

override fun apply(base: Statement?, d: Description?): Statement =
            object : Statement() {
                @Throws(Throwable::class)
                override fun evaluate() {
                    RxJavaPlugins.reset()
                    RxAndroidPlugins.reset()

                    RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
                    RxJavaPlugins.setComputationSchedulerHandler { Schedulers.trampoline() }
                    RxJavaPlugins.setNewThreadSchedulerHandler { Schedulers.trampoline() }
                    RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() }

                    base?.evaluate()
                }
            }
@JakeWharton
Copy link
Member

What version of Android are you running the test on?

@AnastasiaRainMaker
Copy link
Author

I am running unit tests on JVM, Android Studio 3.6.2

@JakeWharton
Copy link
Member

You cannot use RxAndroid in JVM tests because it relies on Android APIs. Message.obtain is somehow returning null which is impossible on Android. Best guess is you're using something like

  testOptions {
    unitTests.returnDefaultValues = true
  }

which will make it have this behavior.

Try using Robolectric or running your tests through instrumentation on an actual emulator or device.

If you still believe it to be a problem with this library then we'll need an executable test case or sample that demonstrates the failure because as far as I can tell this is impossible behavior in normal usage.

@AnastasiaRainMaker
Copy link
Author

I am using returnDefaultValues, actually seems that migrating to gradle plugin 3.6.3 solved it. The tests started passing as before. So I think the issue was with the unitTests.returnDefaultValues part most likely

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants