Lucas Pires
Lucas Pires

Reputation: 23

RxJava2, Android -> Whats wrong in this unittest

I do not know why this error is occurring. I need to test if database Interface is called in successful. I tried for a few hours without success.

Class

class VisitUseCase(private var webService: WebService, private var databaseInterface: SupervisorDatabaseInterface) : VisitUseCaseInterface {
    fun getVisitsFromApi(): Single<List<VisitsItem>> {
            Log.e("API", "API")
            return databaseInterface.getUserToken()
                    .flatMap { it -> webService.getVisits("Token ${it.token}", "future", "true") }
                    .map { it -> it.visits!! }
                    .doOnSuccess { it -> databaseInterface.insertListOfVisits(it) }
        }

databaseInterface.getUserToken("","","") -> return Single - UserToken -

webService.getVisits() -> return Single - RoutineVisit-

map -> ruturn List- Visits -

Test

class VisitUseCaseTest {
    private val immediateScheduler = object : Scheduler() {
        override fun createWorker(): Worker {
            return ExecutorScheduler.ExecutorWorker(Executor { it.run() })
        }
    }


var webService: WebService = Mockito.mock(WebService::class.java)

var databaseInterface: SupervisorDatabaseInterface = Mockito.mock(SupervisorDatabaseInterface::class.java)

var mVisitUseCase: VisitUseCase = VisitUseCase(webService, databaseInterface)


@Before
fun setup() {
    MockitoAnnotations.initMocks(this)
    RxJavaPlugins.setInitIoSchedulerHandler { immediateScheduler }
    RxAndroidPlugins.setInitMainThreadSchedulerHandler { 
    immediateScheduler }
    RxJavaPlugins.setComputationSchedulerHandler { immediateScheduler 
    }
}

@After
fun tearDown() {
    RxJavaPlugins.reset()
    RxAndroidPlugins.reset()
}


@Test
fun `success get from api`() {

    val listSingleVisit = Single.just(listOf<VisitsItem>())

    val userTokenSingle = Single.just(UserToken())

    val routineVisitsSingle = Single.just(RoutineVisits())

    `when`(webService.getVisits("", "", "")).thenReturn(routineVisitsSingle)
    `when`(databaseInterface.getUserToken()).thenReturn(userTokenSingle)

    mVisitUseCase.getVisitsFromApi().test().assertNoErrors()

    verify(databaseInterface, 
    times(1)).insertListOfVisits(listSingleVisit.blockingGet())
}

}

Whats happining

java.lang.AssertionError: Error(s) present: [java.lang.NullPointerException: The single returned by the mapper is null] (latch = 0, values = 0, errors = 1, completions = 0)

    at io.reactivex.observers.BaseTestConsumer.fail(BaseTestConsumer.java:191)
    at io.reactivex.observers.BaseTestConsumer.assertNoErrors(BaseTestConsumer.java:276)
    at test.id.domain.visitUseCase.VisitUseCaseTest.success get from api(VisitUseCaseTest.kt:65)
    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:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.NullPointerException: The single returned by the mapper is null
    at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39)
    at 

io.reactivex.internal.operators.single.SingleFlatMap$SingleFlatMapCallback 
     .onSuccess(SingleFlatMap.java:76)
    at io.reactivex.internal.operators.single.SingleJust.subscribeActual(SingleJust.java:30)
    at io.reactivex.Single.subscribe(Single.java:3096)
    at io.reactivex.internal.operators.single.SingleFlatMap.subscribeActual(SingleFlatMap.java:36)
    at io.reactivex.Single.subscribe(Single.java:3096)
    at io.reactivex.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:34)
    at io.reactivex.Single.subscribe(Single.java:3096)
    at io.reactivex.internal.operators.single.SingleDoOnSuccess.subscribeActual(SingleDoOnSuccess.java:35)
    at io.reactivex.Single.subscribe(Single.java:3096)
    at io.reactivex.Single.test(Single.java:3534)
    ... 25 more

Upvotes: 1

Views: 929

Answers (1)

marianosimone
marianosimone

Reputation: 3606

Your mock setup is not what you want it to be:

`when`(webService.getVisits("", "", "")).thenReturn(routineVisitsSingle)

Will return routineVisitsSingle only if webService.getVisits is called with empty strings, but your code calls it like:

webService.getVisits("Token ${it.token}", "future", "true")

Your mock should be setup with something like this instead:

`when`(webService.getVisits("Token ", "future", "true")).thenReturn(routineVisitsSingle)

It's up to you (and your code's logic) to decide if you want to mock exactly for those values, or you want to use something like any() or other Matchers

Upvotes: 1

Related Questions