Kotlin 使用 Mockk 通过 get/set 来模拟 var

问题描述 投票:0回答:1

我有一个 Kotlin 类,它是 Android 应用程序中 SharedPreferences 的包装器。

class Preferences(private val context: Context) {
    
    private val preferences: SharedPreferences =
        context.getSharedPreferences("name_of_file", Context.MODE_PRIVATE)
    
    // Integers
    var coins: Int
        get() = preferences.getInt(KEY_COINS, 0)
        set(value) = preferences.edit { putInt(KEY_COINS, value) }
    
    var pressure: Int
        get() = preferences.getInt(KEY_PRESSURE, DEFAULT_PRESSURE)
        set(value) = preferences.edit { putInt(KEY_PRESSURE, value) }
}

我需要模拟此类,以便能够在我的视图模型的某些单元测试中使用它。我尝试模拟属性的 get/set 方法,但由于某种原因,我遇到了一些错误,我需要一些帮助。

这就是我尝试模拟 Preferences 类的方式:

private val sharedPreferences = mutableMapOf<String, Any>()
...
val preferences = mockk<Preferences>()
    
    listOf("coins", "pressure").forEach { key ->
        every { preferences getProperty key } returns sharedPreferences[key]
        
        every { preferences setProperty key } answers { // exception on this line
            sharedPreferences[key] = fieldValue
            fieldValue
        }
    }

在运行任何涉及此模拟的测试时,我都会遇到此异常

io.mockk.MockKException: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock

我认为这个错误非常神秘。或者,有没有办法使用

mockk
来模拟这些字段?

我还阅读了here中的示例,我从中获得了此解决方案的灵感,但似乎我缺少一些东西。

android unit-testing kotlin mvvm mockk
1个回答
0
投票

你可以这样做:

every { (preferences setProperty key) value any<Int>() } answers {
    val theValue = args.first() as Int
    // OR val theValue = firstArg<Int>()
    sharedPreferences[key] = theValue
}

或者这个:

val slot = slot<Int>()
every { (preferences setProperty key) value capture(slot) } answers {
    sharedPreferences[key] = slot.captured
}
© www.soinside.com 2019 - 2024. All rights reserved.