Search code examples
gradlenosuchmethoderrorkotlinsource-sets

Kotlin: java.lang.NoSuchMethodError in tests


Is it possible to use Kotlin package functions and package properties in different sourcesets? When I try to do so, I have NoSuchMethodError thrown.


Example

I have Gradle project with Kotlin code and two sourcesets in it, main and test. In main, I have the following code in one of the files:

package ru.ifmo.ctddev.igushkin.dkvs
...
public val payloadSplitter: String = " ### "

In test I try to access payloadSplitter with the following code:

package ru.ifmo.ctddev.igushkin.dkvs
...
public class MessageTests {
    ...
    test fun testParsing() {
        ...
        checkParseAndToString("p1b 345 ${payloadSplitter} set a b c")
    }
    ...
}

And exactly in the first line where payloadSplitter is accessed, at runtime I get

java.lang.NoSuchMethodError: ru.ifmo.ctddev.igushkin.dkvs.DkvsPackage.getPayloadSplitter()Ljava/lang/String;

Other global variables and functions are also inaccessible in test with the same error.


UPD Kotlin team explained the issue and announced the fix here.


Solution

  • For properties and methods outside of classes, Kotlin creates a java class named ${packagename}Package with the properties and methods implemented as static methods and variables. With multiple source-sets, the java class will be created twice, once for each source-set. Your issue is that the test source-set "package class" is hiding the class compiled in the main source-set.

    As mentioned in the comments above, avoid having any top-level properties or methods in the test source-set to prevent the Kotlin compiler from creating this package class in the test output directory.