具有匿名类字段引用原始(非监视)对象的 Mockk 监视类

the*_*eba 6 kotlin mockk

当使用 Mockk 监视 Kotlin 或 Java 类时,如果该类有一个匿名类字段(如 View.OnClickListener),则当字段函数引用父类时,不会反映在监视对象上。

具有匿名类字段的示例类:

class MyClass {
    var myString: String? = null
        set(value) {
            println("myString set to ${value?.hashCode()} for ${this@MyClass.hashCode()}")
            field = value
        }

    val myStringWrapper: StringWrapper = object : StringWrapper {
        val timestamp = System.currentTimeMillis()
        override fun setString(string: String) {
            println("myStringWrapper ${this.hashCode()} for ${this@MyClass.hashCode()}")
            myString = string
        }
    }
    
    fun setString(string: String) {
        myString = string
    }

    interface StringWrapper {
        fun setString(string: String)
    }
}
Run Code Online (Sandbox Code Playgroud)

单元测试示例

    @Test
    fun testSpyAndRealMyClassStringWrapper2() {
        val realMyClass = MyClass()
        println("realMyClass hash is ${realMyClass.hashCode()}")
        realMyClass.myStringWrapper.setString("Hello World")
        println("realMyClass myString value ${realMyClass.myString}")
        println()
        
        val spyMyClass = spyk(MyClass())
        println("spyMyClass hash is ${spyMyClass.hashCode()}")
        spyMyClass.myStringWrapper.setString("Hello World")
        println("spyMyClass myString value ${spyMyClass.myString}")
    }
Run Code Online (Sandbox Code Playgroud)

单元测试结果

realMyClass hash is 896791337
myStringWrapper 1919243391 for 896791337
myString set to -862545276 for 896791337
realMyClass myString value Hello World

spyMyClass hash is 1153593788
myStringWrapper 971441251 for 1519093944
myString set to -862545276 for 1519093944
spyMyClass myString value null
Run Code Online (Sandbox Code Playgroud)

当通过匿名类访问时,Spied 类清楚地显示了与 sied 类不同的哈希码,并且 myString 最终不会被设置(因为它返回 null)。如果间谍的 MyClass 被提取为它自己的变量,则该项目的 myString 字段将返回间谍期望的“Hello World”。