如何在MockK中匹配logger.error方法的匿名对象?
解决方案
一、解决any()匹配失败的问题
你遇到的any()不匹配,是因为Kotlin匿名对象的类型是局部隐式类(格式类似my.package.myClass$myFunction$1),Mockito的any()若未显式指定类型,可能会推断出和实际类型不兼容的匹配器。可以显式指定匹配Any类型:
verify { loggerMock.error(MY_ENUM_VALUE, any<Any>()) }
如果logger.error的第二个参数有明确父类型(比如自定义的LogPayload),也可以指定为该类型,例如any<LogPayload>()。
二、精确匹配匿名对象的字段值
因为匿名对象的类型无法在测试代码中直接引用,只能通过反射或匹配器检查属性:
方法1:用Mockito-Kotlin的match结合反射
通过反射获取匿名对象的字段值,再做断言:
verify { loggerMock.error( eq(MY_ENUM_VALUE), match { obj -> // 获取field0的值 val field0 = obj.javaClass.getDeclaredField("field0").run { isAccessible = true // 突破私有访问限制 get(obj) } // 获取field1的值 val field1 = obj.javaClass.getDeclaredField("field1").run { isAccessible = true get(obj) } // 断言字段值符合预期 field0 == expectedField0 && field1 == expectedField1 } ) }
方法2:替换匿名对象为数据类(推荐)
匿名对象本身不利于测试,建议定义一个数据类替代,让测试逻辑更简洁直观:
// 定义数据类 data class LogDetails(val field0: Field0Type, val field1: Field1Type) // 业务代码中替换匿名对象 logger.error(MY_ENUM_VALUE, LogDetails(field0Value, field1Value)) // 测试代码直接匹配实例 verify { loggerMock.error(MY_ENUM_VALUE, eq(LogDetails(expectedField0, expectedField1))) }
这种方式既保证了代码可读性,也让测试逻辑更清晰。
内容的提问来源于stack exchange,提问作者EnzoMolion
相关产品推荐
相关产品推荐

