Kotlin: java.lang.NoSuchMethodError in tests

Can I use Kotlin package features and package properties in different sets of sources? When I try to do this, I have a NoSuchMethodError .


Example

I have a Gradle project with Kotlin code and its two sources, 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 am trying to access payloadSplitter with the following code:

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

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

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

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


UPD The Kotlin team explained the problem and announced a fix here .

+7
nosuchmethoderror kotlin gradle source-sets
source share
2 answers

For properties and methods outside the classes, Kotlin creates a java class called $ {packagename} A package with properties and methods implemented as static methods and variables. With multiple sets of sources, the java class will be created twice, once for each set of sources. Your problem is that the source test suite "package class" hides the class compiled in the main source set.

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

+5
source share

In addition to what was suggested earlier, I found another workaround: if you need functions or properties at the package level in test , just move the tests to another package, for example. in your test sources:

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

and then do

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

that there is everything from your main package. This will force the Kotlin compiler to generate two non-conflicting package classes, so both can have global members.

+1
source share

All Articles