Kotlin:java.lang.NoSuchMethodError 在测试中
Kotlin: java.lang.NoSuchMethodError in tests
是否可以在不同的源集中使用 Kotlin 包函数和包属性?当我尝试这样做时,我抛出了 NoSuchMethodError
。
例子
我有 Gradle 个项目,其中包含 Kotlin 代码和两个源集,main
和 test
。
在 main
中,我在其中一个文件中包含以下代码:
package ru.ifmo.ctddev.igushkin.dkvs
...
public val payloadSplitter: String = " ### "
在 test
中,我尝试使用以下代码访问 payloadSplitter
:
package ru.ifmo.ctddev.igushkin.dkvs
...
public class MessageTests {
...
test fun testParsing() {
...
checkParseAndToString("p1b 345 ${payloadSplitter} set a b c")
}
...
}
并且恰好在访问 payloadSplitter
的第一行,在运行时我得到
java.lang.NoSuchMethodError: ru.ifmo.ctddev.igushkin.dkvs.DkvsPackage.getPayloadSplitter()Ljava/lang/String;
在test
中也无法访问其他全局变量和函数,并出现同样的错误。
UPD Kotlin 团队解释了这个问题并宣布了修复 here。
对于 classes 之外的属性和方法,Kotlin 创建一个名为 ${packagename} 的 java class 包,其中的属性和方法作为静态方法和变量实现。对于多个源集,java class 将被创建两次,每个源集一次。您的问题是测试源集 "package class" 隐藏了在主源集中编译的 class。
如上面的评论所述,避免在测试源集中包含任何顶级属性或方法,以防止 Kotlin 编译器在测试输出目录中创建此包 class。
除了之前建议的之外,我还找到了另一种解决方法:如果您需要 test
中的包级函数或属性,只需将测试移至不同的包,例如在您的测试源中:
package ru.ifmo.ctddev.igushkin.dkvs.tests
然后
import ru.ifmo.ctddev.igushkin.dkvs.*
这是您主包中的所有内容。这将使 Kotlin 编译器生成两个不冲突的包 类,因此两者都可以有全局成员。
我在测试 kotlin-native 模块时遇到了类似的问题,通过添加以下依赖项解决了这个问题:
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
是否可以在不同的源集中使用 Kotlin 包函数和包属性?当我尝试这样做时,我抛出了 NoSuchMethodError
。
例子
我有 Gradle 个项目,其中包含 Kotlin 代码和两个源集,main
和 test
。
在 main
中,我在其中一个文件中包含以下代码:
package ru.ifmo.ctddev.igushkin.dkvs
...
public val payloadSplitter: String = " ### "
在 test
中,我尝试使用以下代码访问 payloadSplitter
:
package ru.ifmo.ctddev.igushkin.dkvs
...
public class MessageTests {
...
test fun testParsing() {
...
checkParseAndToString("p1b 345 ${payloadSplitter} set a b c")
}
...
}
并且恰好在访问 payloadSplitter
的第一行,在运行时我得到
java.lang.NoSuchMethodError: ru.ifmo.ctddev.igushkin.dkvs.DkvsPackage.getPayloadSplitter()Ljava/lang/String;
在test
中也无法访问其他全局变量和函数,并出现同样的错误。
UPD Kotlin 团队解释了这个问题并宣布了修复 here。
对于 classes 之外的属性和方法,Kotlin 创建一个名为 ${packagename} 的 java class 包,其中的属性和方法作为静态方法和变量实现。对于多个源集,java class 将被创建两次,每个源集一次。您的问题是测试源集 "package class" 隐藏了在主源集中编译的 class。
如上面的评论所述,避免在测试源集中包含任何顶级属性或方法,以防止 Kotlin 编译器在测试输出目录中创建此包 class。
除了之前建议的之外,我还找到了另一种解决方法:如果您需要 test
中的包级函数或属性,只需将测试移至不同的包,例如在您的测试源中:
package ru.ifmo.ctddev.igushkin.dkvs.tests
然后
import ru.ifmo.ctddev.igushkin.dkvs.*
这是您主包中的所有内容。这将使 Kotlin 编译器生成两个不冲突的包 类,因此两者都可以有全局成员。
我在测试 kotlin-native 模块时遇到了类似的问题,通过添加以下依赖项解决了这个问题:
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"