I tried to get response from RxJava2 in Unit test, I found an example how to do it, but i can`t see and response, can yoy help me? Thank you. The code itself has been working for a long time, without problems, and when the tests were required I encountered a problem, similar examples are more or less the same, but everywhere it is done this way, but it does not work for me.
There my code from presenter:
fun register(
email: String,
password: String,
termsEnabled: Boolean,
dayOfBirth: Int,
monthOfBirth: Int,
yearOfBirth: Int,
formattedBirthDate: String,
state: String?
) {
addDisposable(
registerUseCase.run(
RegisterUseCase.RegisterRequest(
email,
password,
termsEnabled,
formattedBirthDate,
state ?: ""
)
)
.observeOn(mainThreadScheduler)
.subscribeOn(backgroundScheduler)
.subscribe(
{
getView?.showEmptyPassword()
}, {
getView?.showEmptyPassword()
}
)
)
}
And test:
@Before
fun setUp() {
RxAndroidPlugins.setInitMainThreadSchedulerHandler {
Schedulers.trampoline() }
MockitoAnnotations.initMocks(this)
presenter = CreateAccountPresenter(
mainThreadScheduler,
backgroundScheduler,
registerUseCase,
getUserDataUseCase,
getStatesUseCase,
regexUtils,
router,
resourceUtils,
deviceSharedPreferences
)
presenter.setView(view)
}
@Test
fun testRegister() {
given(registerUseCase.run(RegisterUseCase.RegisterRequest(
EMAIL, PASSWORD, true,
FORMATTED_BIRTHDAY, STATE))
).willReturn(Single.just(RegisterResponse(false, "ok", "id")))
presenter.register(
EMAIL,
PASSWORD,
true,
1,
1,
1,
FORMATTED_BIRTHDAY,
STATE)
verify(view).showEmptyPassword()
}
But issue is:
Wanted but not invoked:
view.showEmptyPassword();
-> at
com.unikrn.esports.umode.CreateAccountPresenterTest.testRegister(CreateAccountPresenterTest.kt:179)
Actually, there were zero interactions with this mock.
The issue is that you're doing some computation in a background thread and, even being mocked, it doesn't have enough time to finish before the verify
invocation
Since you're already injecting the schedulers for your operations, specify that both of them are trampoline
so everything runs in the same thread
@Before
fun setUp() {
presenter = CreateAccountPresenter(
Schedulers.trampoline(),
Schedulers.trampoline(),
...
)
}
Worst case scenario, you can add some blocker element (such as a Semaphore
) that blocks the test execution and you release it in one of your view
methods (that you'll need to stub)
As per the docs, Schedulers.trampoline() schedules all tasks in the current thread so everything will be blocking. In case you want to directly use some schedulers like Schedulers.io()
you'll need to override them in a similar way you're doing now with
RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() } // Override MainThreadScheduler
Note that the previous snippet is just an example and you'll need to adapt it