juliocbcotta
02/14/2022, 10:21 AMoverride fun sumSelectedFees(): Single<Float> = rxSingle(workDispatcher) {
dao.findDeliveryModeShippingOptions(true)
.fold(0f) { total, shippingOption -> total + shippingOption.feeValue }
}
and I trying to call this in my test
@Test
fun `should sum all inserted fees for delivery`() = runTest {
val dataSource = dataSource = DeliveryModesDataSourceImpl(dao, UnconfinedTestDispatcher())
dataSource.sumSelectedFees()
.test()
.assertValue(0f)
}
but my test is failing since the test is not waiting the rx call .test()
to complete.. I Used UnconfinedTestDispatcher
here, but I am not sure what I dispatcher I should be using in this case.Sam
02/14/2022, 10:28 AMworkDispatcher
you're passing to rxSingle
. The test doesn't know anything about that dispatcher and so can't wait for it to finish.sumSelectedFees
method.override fun sumSelectedFees(context: CoroutineContext = workDispatcher): Single<Float> = rxSingle(context) {
...
juliocbcotta
02/14/2022, 10:30 AMval dataSource = DeliveryModesDataSourceImpl(dao, UnconfinedTestDispatcher())
Sam
02/14/2022, 10:30 AMUnconfinedTestDispatcher
you use isn't the same one being used by runTest
TestScope
and pass it to the DeliveryModesDataSourceImpl
instead of creating a new UnconfinedTestDispatcher
runTest
and the DeliveryModesDataSourceImpl
juliocbcotta
02/14/2022, 10:36 AMprivate val dispatcher = UnconfinedTestDispatcher()
dataSource = DeliveryModesDataSourceImpl(dao, dispatcher)
runTest(dispatcher) {...
Still not workingSam
02/14/2022, 10:39 AM.test()
and before the .assertValue()
you need to call runCurrent()
UnconfinedTestDispatcher
won't always run all of its coroutines without a call to runCurrent
, if they're nested/launched in more complicated waysjuliocbcotta
02/14/2022, 10:44 AMSam
02/14/2022, 10:45 AMrxSingle
. There must be a trick we're missing.juliocbcotta
02/14/2022, 10:47 AMDmitry Khalanskiy [JB]
02/14/2022, 11:46 AMUnconfinedTestDispatcher(testScheduler)
instead of just UnconfinedTestDispatcher
. Otherwise, there's no link between runTest
and the dispatcher, unless there's Dispatchers.setMain
somewhere.juliocbcotta
02/14/2022, 1:44 PMDispatchers.setMain
, but I am using runTest(dispatcher)
, where val dispatcher = UnconfinedTestDispatcher()
Dmitry Khalanskiy [JB]
02/14/2022, 1:55 PMUnconfinedTestDispatcher()
just creates a new dispatcher, not related to runTest
.juliocbcotta
02/14/2022, 1:59 PMrxSingle
to publish in a sync way so .test()
will be sync and so my test.
I passed around the Dispatcher to every place I could find, but my tests are still failing.Dmitry Khalanskiy [JB]
02/14/2022, 2:01 PM@Test
fun `should sum all inserted fees for delivery`() = runTest {
val dataSource = dataSource = DeliveryModesDataSourceImpl(dao, UnconfinedTestDispatcher(testScheduler)) // <--- modified here
dataSource.sumSelectedFees()
.test()
.assertValue(0f)
}
juliocbcotta
02/14/2022, 2:06 PMexpected: 0.0 (class: Float) but was: [] (latch = 1, values = 0, errors = 0, completions = 0)
java.lang.AssertionError: expected: 0.0 (class: Float) but was: [] (latch = 1, values = 0, errors = 0, completions = 0)
private val dispatcher = UnconfinedTestDispatcher()
suspend fun bar() = withContext(dispatcher) {
withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
1
}
}
@Test
fun foo() = runTest(dispatcher) {
rxSingle(dispatcher) { bar() }
.test()
.assertValue(1)
.assertComplete()
}
Dmitry Khalanskiy [JB]
02/14/2022, 2:21 PMtest()
in RxJava not awaiting the completion. For example, here is the same issue, without any coroutines:
@Test
fun foo2() {
val single = Single.create<Int> { emitter ->
thread {
Thread.sleep(10)
emitter.onSuccess(1)
}
}
single.test().assertValue(1).assertComplete()
}
It may work if there's only one thread, but <http://Dispatchers.IO|Dispatchers.IO>
uses other threads.
This can be fixed with
@Test
fun foo() = runTest(dispatcher) {
rxSingle(dispatcher) { bar() }
.test()
.await() // <-------- waits for completion before checking the results
.assertValue(1)
.assertComplete()
}
juliocbcotta
02/14/2022, 2:32 PM