线程 "Test worker" java.lang.IllegalStateException 中的异常:具有主调度程序的模块未能初始化
Exception in thread "Test worker" java.lang.IllegalStateException: Module with the Main dispatcher had failed to initialize
嘿,我遇到了这种奇怪的问题。我不明白为什么这会导致我的单元测试。有人可以指导我身边缺少什么吗。
Exception in thread "Test worker" java.lang.IllegalStateException: Module with the Main dispatcher had failed to initialize. For tests Dispatchers.setMain from kotlinx-coroutines-test module can be used
at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.missing(MainDispatchers.kt:118)
at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.isDispatchNeeded(MainDispatchers.kt:96)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:319)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at io.mockk.proxy.jvm.advice.MethodCall.call(MethodCall.kt:14)
at io.mockk.proxy.jvm.advice.SelfCallEliminatorCallable.call(SelfCallEliminatorCallable.kt:14) .....
这是我的单元测试文件。我不明白为什么会出现这个问题。
UnitTest.kt
class XYZViewModelTest {
@get:Rule
val koinTestRule = KoinTestRule.create {
modules(utilsModule)
}
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
private lateinit var mockViewModel: XYZViewModel
..../// more declartions
@Before
fun setUp() {
MockKAnnotations.init(this, relaxed = true)
loadKoinModules(module {
listOf(
factory { mockSessionHelper }
)
})
mockViewModel = spyk(XYZViewModel())
}
./// function
}
进行单元测试时,您必须将 Dispatchers.Main 替换为与默认情况下不同的调度程序,因为 Dispatchers.Main 的默认实现在 运行 不存在时不存在完整的应用程序。为此,如果您还没有 kotlinx-coroutines-test
测试依赖项,则需要:
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0'
您可以创建一个协程测试规则来在每次测试之前和之后进行设置,这样您就可以简化在每个测试中的处理 classes。
将其放入自己的文件中:
@ExperimentalCoroutinesApi
class MainDispatcherRule(val dispatcher: TestDispatcher = StandardTestDispatcher()): TestWatcher() {
override fun starting(description: Description?) = Dispatchers.setMain(dispatcher)
override fun finished(description: Description?) = Dispatchers.resetMain()
}
然后将规则添加到您的测试中 class:
@ExperimentalCoroutinesApi
@get:Rule
val mainDispatcherRule = MainDispatcherRule()
您使用协程的测试应该使用 return runTest
函数,因此它们应该如下所示:
@ExperimentalCoroutinesApi
@Test
fun fooTest() = runTest {
//...
}
抱歉,如果我遗漏了什么。最新的 kotlinx-coroutines-test
1.6.0 版本有很多变化,我还没有跟上它的速度。
嘿,我遇到了这种奇怪的问题。我不明白为什么这会导致我的单元测试。有人可以指导我身边缺少什么吗。
Exception in thread "Test worker" java.lang.IllegalStateException: Module with the Main dispatcher had failed to initialize. For tests Dispatchers.setMain from kotlinx-coroutines-test module can be used
at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.missing(MainDispatchers.kt:118)
at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.isDispatchNeeded(MainDispatchers.kt:96)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:319)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at io.mockk.proxy.jvm.advice.MethodCall.call(MethodCall.kt:14)
at io.mockk.proxy.jvm.advice.SelfCallEliminatorCallable.call(SelfCallEliminatorCallable.kt:14) .....
这是我的单元测试文件。我不明白为什么会出现这个问题。
UnitTest.kt
class XYZViewModelTest {
@get:Rule
val koinTestRule = KoinTestRule.create {
modules(utilsModule)
}
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
private lateinit var mockViewModel: XYZViewModel
..../// more declartions
@Before
fun setUp() {
MockKAnnotations.init(this, relaxed = true)
loadKoinModules(module {
listOf(
factory { mockSessionHelper }
)
})
mockViewModel = spyk(XYZViewModel())
}
./// function
}
进行单元测试时,您必须将 Dispatchers.Main 替换为与默认情况下不同的调度程序,因为 Dispatchers.Main 的默认实现在 运行 不存在时不存在完整的应用程序。为此,如果您还没有 kotlinx-coroutines-test
测试依赖项,则需要:
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0'
您可以创建一个协程测试规则来在每次测试之前和之后进行设置,这样您就可以简化在每个测试中的处理 classes。
将其放入自己的文件中:
@ExperimentalCoroutinesApi
class MainDispatcherRule(val dispatcher: TestDispatcher = StandardTestDispatcher()): TestWatcher() {
override fun starting(description: Description?) = Dispatchers.setMain(dispatcher)
override fun finished(description: Description?) = Dispatchers.resetMain()
}
然后将规则添加到您的测试中 class:
@ExperimentalCoroutinesApi
@get:Rule
val mainDispatcherRule = MainDispatcherRule()
您使用协程的测试应该使用 return runTest
函数,因此它们应该如下所示:
@ExperimentalCoroutinesApi
@Test
fun fooTest() = runTest {
//...
}
抱歉,如果我遗漏了什么。最新的 kotlinx-coroutines-test
1.6.0 版本有很多变化,我还没有跟上它的速度。