Andrew Steinmetz
09/21/2021, 9:21 PMSuspendExecutor
and was wondering if anybody had a sample project where they could get a runBlockingTest
to work? After some research it seems like the runBlockingTest
in the coroutines test library is just supported on the JVM, but there is a workaround to get it to work per this comment. After adding that to my project, I still seem to run into a few issues when trying to run the test.
import com.arkivanov.mvikotlin.core.store.StoreFactory
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
import com.plusmobileapps.shared.db.Activity
import com.plusmobileapps.wolfpack.activity.list.ActivityListStoreProvider
import com.plusmobileapps.wolfpack.di.DEFAULT_DISPATCHER_TAG
import com.plusmobileapps.wolfpack.di.MAIN_DISPATCHER_TAG
import com.plusmobileapps.wolfpack.mocks.ActivityRepositoryMock
import com.plusmobileapps.wolfpack.runBlockingTest
import kotlinx.coroutines.Dispatchers
import org.kodein.di.DI
import org.kodein.di.bind
import org.kodein.di.singleton
import kotlin.coroutines.CoroutineContext
import kotlin.test.Test
import kotlin.test.assertEquals
class ActivityListStoreTest {
private val storeFactory = DefaultStoreFactory
private val repository = ActivityRepositoryMock()
private val di = DI {
bind<CoroutineContext>(MAIN_DISPATCHER_TAG) { singleton { testCoroutineContext } }
bind<CoroutineContext>(DEFAULT_DISPATCHER_TAG) { singleton { testCoroutineContext } }
bind<ActivityRepository> { singleton { repository } }
bind<StoreFactory> { singleton { storeFactory } }
}
@Test
fun foo() = runBlockingTest {
val activity = Activity(1L, "", true)
repository.addActivity(activity)
val store = ActivityListStoreProvider(di).provide()
assertEquals(listOf(activity), store.state.activities)
}
}
• For ios, keep getting an InvalidMutabilityException
which I think is because the DI gets frozen inside the test because once something is retrieved from DI it throws the exception?
• Then for android, keep getting java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked.
which am I supposed to import the coroutine test library on jvm tests to get them to work?
I'm a little lost in the weeds trying to figure this out and might even consider switching to Reaktive as it seems to have a pretty good testing support from looking at the todo sample tests. Any help is greatly appreciated!Arkadii Ivanov
09/21/2021, 10:11 PMDI
containers seems like captured by runBlockingTest
and frozen. I usually supply dependencies via direct arguments to a Store factories. You can try creating DI
inside the runBlockingTest
block.
Re issue 2: You should avoid using the Main dispatcher in unit tests. It's not clear what is the testCoroutineContext
in your case. You can try using Dispatchers.Unconfined
.Andrew Steinmetz
09/21/2021, 11:08 PMrunBlockingTest {}
freezes anything inside the block because removing DI
and injecting the properties does fix the the InvalidMutabilityException
on the original crash from storefactory, however if I try to touch the repository mock it will freeze it and then throw an exception on that 🙃
testCoroutineContext
was something I found as a workaround in this github issue since that TestDispatcher
is a JVM only library.
I was hoping to use coroutines since I was also writing a backend using Ktor which uses coroutines, but I might just have the frontend work off of Reaktive since coroutines multiplatform testing has no official support yet.Arkadii Ivanov
09/21/2021, 11:25 PMensureNeverFrozen
function and call it on your repository before passing to the Store. It will throw an exception when the repository got frozen, not when it is used later.
You can try using Dispatchers.Unconfined and pass it to the Store and to its SuspendExecutor and/or SuspendBootstrapper. By default they both use Dispatchers.Main.Andrew Steinmetz
09/22/2021, 4:37 PMArkadii Ivanov
09/22/2021, 4:38 PM