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.Sam
02/14/2022, 10:28 AMsumSelectedFees method.Sam
02/14/2022, 10:28 AMSam
02/14/2022, 10:29 AMoverride 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 AMSam
02/14/2022, 10:32 AMUnconfinedTestDispatcher you use isn't the same one being used by runTestSam
02/14/2022, 10:33 AMTestScope and pass it to the DeliveryModesDataSourceImpl instead of creating a new UnconfinedTestDispatcherSam
02/14/2022, 10:35 AMrunTest and the DeliveryModesDataSourceImpljuliocbcotta
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()Sam
02/14/2022, 10:40 AMUnconfinedTestDispatcher 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)juliocbcotta
02/14/2022, 2:10 PMprivate 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