如何用MockK测试Kotlin挂起函数以实现100%分支覆盖率?
解决Kotlin单元测试分支覆盖率不达标的问题
针对你遇到的三个覆盖率问题,逐个给出具体解决办法:
1. MyRepository中checkService.check分支未覆盖+mockk(relaxed=true)后覆盖率为0
- mock对象用错了:你不该mock MyRepository本身,
mockk(relaxed=true)会让MyRepository的所有方法都返回默认值,真实代码根本不会执行,自然覆盖率为0。正确做法是:mock MyRepository依赖的CheckService,然后实例化真实的MyRepository传入这个mock的CheckService。 - 覆盖check的所有分支:分别模拟
checkService.check(value)返回true和false的场景,触发fetchData里的不同分支逻辑。示例代码:val checkService = mockk<CheckService>() val myRepository = MyRepository(checkService) // 用真实实例 @Test fun `fetchData when check passes`() { every { checkService.check(any()) } returns true // 调用fetchData并验证对应逻辑 } @Test fun `fetchData when check fails`() { every { checkService.check(any()) } returns false // 调用fetchData并验证错误分支逻辑 }
2. TestSample中mock的TestUserRepository.getCurrentUser()无法100%覆盖
mock对象会跳过真实代码执行,所以你mock了TestUserRepository后,getCurrentUser的真实逻辑根本没跑,覆盖率自然为0。解决办法:
- 不要mock TestUserRepository,直接用真实实例(如果它没有复杂外部依赖的话)。
- 如果TestUserRepository有依赖,就mock它的依赖,再实例化真实的TestUserRepository,然后构造不同的输入/依赖状态,覆盖getCurrentUser的所有分支(比如用户存在、用户不存在的情况)。
3. TestSample2含delay的fetchData覆盖率不达标
delay是协程挂起函数,测试时需要正确处理协程环境,确保所有挂起逻辑都执行完毕:
- 使用kotlinx-coroutines-test库中的
runTest函数包裹测试代码,它会自动跳过真实延迟,同时保证协程执行完成,不会因为延迟导致部分逻辑没覆盖到。 - 确保触发fetchData的所有分支:比如正常流程、异常流程(比如延迟前的逻辑出错),分别编写测试用例覆盖。示例代码:
@Test fun `test fetchData with delay`() = runTest { val repo = TestSample2() val result = repo.fetchData() // 验证结果,确保delay后的逻辑也被执行 } @Test fun `test fetchData error branch`() = runTest { // 模拟触发fetchData中的错误分支(比如依赖报错) val repo = TestSample2(mockErrorDependency) assertFailsWith<Exception> { repo.fetchData() } }
内容的提问来源于stack exchange,提问作者pnkj
相关产品推荐
相关产品推荐

