Marco Righini
01/20/2021, 10:53 PMclass CoroutinesReactiveTest {
private val dep = mock<Dep>()
private val underTest = UnderTest(dep)
@Test
fun `Test someOtherMethod called`() = runBlocking {
underTest.methodToTest().test()
verify(dep).someMethod() // Commenting this line test passes
verify(dep).suspendingFun()
verify(dep).someOtherMethod()
}
}
class Dep {
fun someMethod() {
println("someMethod called")
}
suspend fun suspendingFun() {
delay(100)
println("suspendingFun called")
}
fun someOtherMethod() {
println("someOtherMethod called")
}
}
class UnderTest(private val dep: Dep) {
fun methodToTest(): Completable {
return Completable.fromCallable { dep.someMethod() }
.andThen(rxCompletable { dep.suspendingFun() })
.andThen(Completable.fromCallable { dep.someOtherMethod() })
}
}
commenting the first verify test passesMarcelo Hernandez
01/22/2021, 9:06 PMtest()
is not a blocking function as far as I’m aware, so it will return immediately. However, both rxCompletable
and delay()
operate on Dispatchers.Default
by default. So I’m wondering if somehow test()
is returning immediately but your delay()
is operating asynchronously by the time you run your verify()
calls.runBlocking
will wait for all suspend
code to return but I don’t think it guarantees that these suspend functions return before you make the verify
calls.runBlocking
for runBlockingTest
so that your tests do not actually delay
.Marco Righini
01/24/2021, 7:51 AMMarcelo Hernandez
01/26/2021, 12:10 AMrxCompletable
right?rxCompletable { … }
is used with all the default parameters, it will use Dispatchers.Default
. Which means in your test environment, there will be thread hopping. I have had to work around this by explicitly passing in a Dispatcher
which I have set up as part of my Dependency Injection graph.
// Where dispatchers is my own wrapper around static Dispatchers
rxCompletable(dispatchers.default) { … }