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 .Arkadii Ivanov
09/21/2021, 10:49 PMAndrew 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