14

是否可以在不同的源集中使用 Kotlin 包函数和包属性?当我尝试这样做时,我已经NoSuchMethodError抛出了。


例子

我有带有 Kotlin 代码和两个源集的 Gradle 项目,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 团队解释了这个问题并在这里宣布了修复。

4

3 回答 3

14

对于类之外的属性和方法,Kotlin 创建了一个名为 ${packagename}Package 的 java 类,其中属性和方法实现为静态方法和变量。对于多个源集,java 类将被创建两次,每个源集一次。您的问题是测试源集“包类”隐藏了在主源集中编译的类。

正如上面评论中提到的,避免在测试源集中包含任何顶级属性或方法,以防止 Kotlin 编译器在测试输出目录中创建这个包类。

于 2015-05-29T07:40:35.600 回答
5

除了之前建议的之外,我还发现了另一种解决方法:如果您需要包级函数或属性,test只需将测试移动到不同的包中,例如在您的测试源中:

 package ru.ifmo.ctddev.igushkin.dkvs.tests

然后做

 import ru.ifmo.ctddev.igushkin.dkvs.*

这是您主包中的所有内容。这将使 Kotlin 编译器生成两个不冲突的包类,因此两者都可以具有全局成员。

于 2015-06-01T20:30:50.790 回答
0

我在测试 kotlin-native 模块时遇到了类似的问题,通过添加这个依赖项来修复它:

testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
于 2018-11-27T23:15:54.800 回答