如何在Mockk单元测试中验证不同CoroutineScope的方法调用?
如何验证CoroutineScope中执行的依赖方法调用
我尝试验证依赖对象中的方法是否被调用,但由于该方法在不同的CoroutineScope中执行,coVerify始终验证失败。请问如何验证someMethod()已被调用?
SUT代码
class SomeClass( private val coroutineScope: CoroutineScope, private val someDependency: SomeDependency ) { fun run() { coroutineScope.launch { someDependency.someMethod() } } }
依赖类代码
class SomeDependency { fun someMethod() { println("SomeDependency.someMethod") } }
失败的测试代码
class SomeClassTest { @MockK(relaxed = true) private lateinit var someDependency: SomeDependency private val testScope = TestScope() private lateinit var someClass: SomeClass @Before fun setup() { MockKAnnotations.init(this) someClass = SomeClass( testScope, someDataSource // 这里存在笔误,应该是someDependency ) } @Test fun `when run, should call someDependency someMethod`() = runTest { someClass.run() coVerify { someDependency.someMethod() } } }
解决方案
1. 手动等待TestScope中的协程完成
runTest不会自动等待你自定义的testScope内的协程执行完毕,需要显式调用testScope.advanceUntilIdle()或testScope.runCurrent()来触发所有挂起任务执行:
@Test fun `when run, should call someDependency someMethod`() = runTest { someClass.run() testScope.advanceUntilIdle() // 等待testScope中所有协程完成 coVerify { someDependency.someMethod() } }
2. 使用runTest内置的CoroutineScope
直接将runTest提供的CoroutineScope传给SUT,这样runTest会自动管理该Scope下的所有协程,无需手动等待:
class SomeClassTest { @MockK(relaxed = true) private lateinit var someDependency: SomeDependency private lateinit var someClass: SomeClass @Before fun setup() { MockKAnnotations.init(this) } @Test fun `when run, should call someDependency someMethod`() = runTest { someClass = SomeClass(this, someDependency) someClass.run() coVerify { someDependency.someMethod() } } }
3. 修复测试代码中的笔误
原测试代码的setup方法中,初始化SomeClass时传入的是someDataSource,但实际变量名是someDependency,这会导致SUT使用的不是Mock对象,直接导致验证失败,必须修正:
@Before fun setup() { MockKAnnotations.init(this) someClass = SomeClass( testScope, someDependency // 修正笔误 ) }
内容的提问来源于stack exchange,提问作者Oleh Liskovych
相关产品推荐
相关产品推荐

