Android Kotlin中用Mockk测试工具类时遇MockKException错误求助
解决MockK测试中「Missing mocked calls inside every { ... } block」错误
错误原因
你试图mock真实的TestApp实例的方法,但MockK的every {}语法仅能作用于MockK创建的mock/spy对象,真实对象的方法调用无法被MockK拦截,因此触发该错误。
你的代码问题点
private val testApp = TestApp(mockk(relaxed = true)):创建的是TestApp的真实实例,而非MockK代理的mock/spy对象,导致every {}无法生效。- 构造TestApp时未使用已定义的
context变量,属于冗余代码。 MockkAnnotaions.init拼写错误(正确为MockkAnnotations.init),且relaxUnion参数不存在,应为relaxUnitFun = true。Build.VERSION.RELEASE返回类型是String,测试中用return 11会存在类型不匹配问题。
修复方案
方案一:用Spy对象Mock指定方法
如果需要mockgetOSNumber()的返回值,不需要执行真实逻辑,可以用spyk包装真实实例,既能保留对象原有行为,又能单独mock目标方法:
class TestAppTest { private val context = mockk<Context>(relaxed = true) private lateinit var testApp: TestApp @Before fun setup() { MockkAnnotations.init(this, relaxUnitFun = true) testApp = spyk(TestApp(context)) // 用spyk包装真实实例 } @Test fun testOs() { // Mock getOSNumber方法的返回值(注意是String类型) every { testApp.getOSNumber() } returns "11" val number = testApp.getOSNumber() assertEquals("11", number) } }
方案二:用Robolectric测试真实逻辑
如果要验证getOSNumber()的真实逻辑(返回系统版本号),由于Build.VERSION是Android框架类,本地单元测试无法直接获取真实值,需用Robolectric模拟Android环境:
- 添加Robolectric依赖(build.gradle.kts):
testImplementation("org.robolectric:robolectric:4.12.1")
- 编写测试代码:
@RunWith(RobolectricTestRunner::class) @Config(sdk = [30]) // 指定模拟的Android SDK版本(对应Android 11) class TestAppTest { private val context = ApplicationProvider.getApplicationContext<Context>() private val testApp = TestApp(context) @Test fun testOs() { val number = testApp.getOSNumber() assertEquals("11", number) // Robolectric会返回指定SDK的版本号 } }
内容的提问来源于stack exchange,提问作者Chait
相关产品推荐
相关产品推荐

