如何用MockK模拟带多参数的私有构造方法(Kotlin)
用MockK模拟Foo.Bla的私有构造并mock其属性
针对你要mock Foo.Bla中property1和property2的需求,因为Bla的构造是私有且属性为final,可通过以下两种方式实现:
方法一:反射调用私有构造 + 传入Mock对象
直接通过反射调用Bla的私有构造,将预先mock好的CustomType1和CustomType2实例传入,这样Bla实例的属性自然就是mock对象:
- Mock属性类型实例
// 创建CustomType1和CustomType2的mock对象,复杂类可加relaxed=true生成宽松mock val mockType1 = mockk<CustomType1>() val mockType2 = mockk<CustomType2>(relaxed = true)
- 反射调用私有构造
// 获取Bla类的私有构造方法 val blaConstructor = Foo.Bla::class.java.getDeclaredConstructor( CustomType1::class.java, CustomType2::class.java ) // 开启构造方法的可访问权限 blaConstructor.isAccessible = true // 传入mock对象创建Bla实例 val blaInstance = blaConstructor.newInstance(mockType1, mockType2)
- 操作Mock属性
现在可以直接对mock对象进行Stubbing或验证:
// 打桩:指定mockType1方法的返回值 every { mockType1.someMethod() } returns "mocked value" // 验证:确认mockType2的方法被调用过一次 verify(exactly = 1) { mockType2.someOtherMethod() }
方法二:用MockK的mockkConstructor拦截构造
利用MockK的构造拦截能力,直接替换Bla实例的属性为mock对象,无需手动反射:
// 预先创建mock属性 val mockType1 = mockk<CustomType1>() val mockType2 = mockk<CustomType2>() // 拦截Foo.Bla的所有构造调用 mockkConstructor(Foo.Bla::class) { // 替换property1和property2为mock对象 every { anyConstructed<Foo.Bla>().property1 } returns mockType1 every { anyConstructed<Foo.Bla>().property2 } returns mockType2 } // 此时无论通过何种方式创建Bla实例,属性都会是mock对象 val blaInstance = Foo.Bla::class.java.getDeclaredConstructor( CustomType1::class.java, CustomType2::class.java ).newInstance(mockk(), mockk())
依赖说明
确保测试依赖中包含MockK核心库:
// Gradle示例 testImplementation "io.mockk:mockk:1.13.8"
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

