如何在测试中使用Mockito或PowerMock模拟Kotlin扩展功能?既然它们在静态上解决了,应该将它们作为静态方法调用或非静态测试?
我认为 MOCKK 可以帮助您。
它支持模拟扩展功能。
您可以使用它模拟整个对象扩展:
data class Obj(val value: Int)
class Ext {
fun Obj.extensionFunc() = value + 5
}
with(mockk<Ext>()) {
every {
Obj(5).extensionFunc()
} returns 11
assertEquals(11, Obj(5).extensionFunc())
verify {
Obj(5).extensionFunc()
}
}
如果您扩展是整个模块的,这意味着它在文件中声明(不在class
内(,则应以这种方式模拟它:
data class Obj(val value: Int)
// declared in File.kt ("pkg" package)
fun Obj.extensionFunc() = value + 5
mockkStatic("pkg.FileKt")
every {
Obj(5).extensionFunc()
} returns 11
assertEquals(11, Obj(5).extensionFunc())
verify {
Obj(5).extensionFunc()
}
通过添加 mockkStatic("pkg.FileKt")
行,并用宣布扩展名的软件包和文件的名称(示例中的 pkg.File.kt
(。
可以在此处找到更多信息:网站和github
实例扩展功能可以在Mockito-Kotlin的帮助下进行固定和验证:
data class Bar(thing: Int)
class Foo {
fun Bar.bla(anotherThing: Int): Int { ... }
}
val bar = Bar(thing = 1)
val foo = mock<Foo>()
with(foo) {
whenever(any<Bar>().bla(any()).doReturn(3)
}
verify(foo).apply {
bar.bla(anotherThing = 2)
}
首先,Mockito知道 nothing kotlin特定语言构造。最后,Mockito将在字节代码中以外观。Mockito只能理解它在那里发现的东西以及看起来像Java语言构造的东西。
含义:要肯定,您可能需要使用Javap来重新组装编译的ClassFiles来确定要模拟的方法的确切名称/签名。
显然:当该方法为 static 时,您必须使用用户powermock或jmockit;如果没有,您应该更喜欢使用Mockito。
从Java的角度来看,您只需避免嘲笑静态东西即可;但是,当然,现在有不同想法/概念的不同语言融合在一起。
i使用 MOCKK library。
对于扩展文件写Java名称,如下:
@file:JvmName(name = "ExtensionUtils")
package myproject.extension
...
,对于快速代码,我创建了使用不同扩展模拟的文件:
object FastMock {
fun extension() = mockkStatic("myproject.extension.ExtensionUtils")
fun listExtension() = mockkStatic("myproject.extension.ListExtensionUtils")
}
在测试中致电以下:
FastMock.listExtension()
every { itemList.move(from, to) } returns Unit
使用Mockk库,
给定最高级别(在类中未声明(ContextExt.kt
文件中的扩展方法,例如:
Context.doSomething(param1: Int, param2: String = "default") : Int {
// Does something that wouldn't work in your test environment
}
要模拟它,我们可以做以下操作:
MyTestClass {
companion object {
private const val MOCKED_VALUE = 10
}
...
@Before
fun before() {
mockkStatic("com.my.package.ContextExtKt")
every { any<Context>().doSomething(any(), any()) } returns MOCKED_VALUE
}
}
有几件事要小心:
- Argyou提供给Mockkstatic的是文件的包装名称,如文件的第一行 文件名 'kt'。例如,对于包装
com.my.package
中的文件ContextExt.kt
,您需要:mockkStatic("com.my.package.ContextExtKt")
- 即使它们具有默认值,也将所有ARG提供给您要模拟的扩展方法。如果需要,请使用特定值,否则请使用
any()
。