我在Kotlin中有一个包含一些包级函数的文件 .
//Logger.kt
fun info(tag : String, message : String){
...
}
fun error{....}
我正在测试一个调用这个kotlin文件函数的类的函数,我想嘲笑它们 . 我知道包级函数就像Java中的静态方法一样,所以我一直在考虑使用PowerMock .
//MyClass: Class that calls Logger.kt functions
class MyClass {
fun myFunction(){
info("TAG", "Hello world!")
}
}
有任何想法吗?
2 回答
您可以使用PowerMock . 正如您已经指出的那样,Kotlin为文件
Logger.kt
中的顶级函数生成一个静态Java类,名为LoggerKt.java
. 如果您愿意,可以通过使用@file:JvmName(“...“)
注释文件来更改它 . 因此你可以这样做:我试图让它在Kotlin中运行,但我没有找到一种方法来使得Kotlin生成的
Logger
Java类可用作类文字,以便能够将它用于@PrepareForTest
注释 . 虽然有可能to reference the generated Java class在Kotlin .您可以使用一种解决方法来模拟Kotlin的顶级功能 .
Explanation
@PrepareForTest
注释确实有2个参数,用于提供您想要模拟某些内容的上下文(类)或者您将要使用的模拟内容 .第一个参数是
value
,如果输入Class<?>[]
:这里你可以提供一个类数组 . 例如:第二个参数
fullyQualifiedNames
类型为String[]
:在这里,您可以提供具有类的完全限定名称的数组 . 例如:假设我们有一个名为“MyUtils.kt”的Kotlin文件,它只包含顶级函数 . 如您所知,您无法从Kotlin文件引用MyUtilsKt类,但可以从Java引用 . 这意味着生成了静态类(我还没有足够的知识为您提供有关此内容的更多详细信息)并且它具有完全限定的名称 .
Solution
这个解决方案并不完美 . 我在我们的代码库上实现它,它似乎工作 . 当然可以改进 .
TopLevelFunctionClass.kt
的Kotlin文件,其中我添加了仅包含顶级函数的"classes"的完全限定名称 .internal const val MyUtilsKt = "com.x.y.z.MyUtilsKt"
不幸的是,我不得不对名称进行硬编码,因为注释参数必须是编译时常量 .
@PrepareForTest
注释,如下所示:MyUtils.kt
中的顶级函数:测试方法:
副作用:如果您重命名包含顶级函数的kotlin文件,您还必须更改
TopLevelFunctionClass.kt
中定义的常量 . 避免重命名问题的可能解决方案是添加:@file:JvmName("The name you want for this file")
. 如果你'll have 2 files with the same name you' ll得到重复JVM类名称错误 .