2015-05-25 6 views
7

Возможно ли использовать функции пакета Kotlin и свойства пакета в разных наборах источников? Когда я пытаюсь сделать это, у меня есть NoSuchMethodError.Kotlin: java.lang.NoSuchMethodError в тестах


Пример

У меня есть проект Gradle с Котлином кодом и два sourcesets в нем, 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 Котлин команда объяснила этот вопрос и объявил исправление here.

+1

Есть ли у вас какие-либо функции/свойства верхнего уровня в файле ru.ifmo.ctddev.igushkin.dkvs в тестах? –

+0

Как вы проводите тесты? Не могли бы вы разместить свою конфигурацию gradle? Похоже, что тестовый пакет скомпилирован против основного пакета, но работает без него. –

+0

@SalomonBRYS, https://github.com/h0tk3y/dkvs/blob/master/build.gradle - вот оно. – hotkey

ответ

5

Для свойств и методов вне классов Kotlin создает класс java с именем $ {packagename} Пакет со свойствами и методами, реализованными как статические методы и переменные. С несколькими наборами источников класс java будет создан дважды, один раз для каждого набора источников. Ваша проблема в том, что исходный набор тестов «класс пакета» скрывает класс, скомпилированный в основном исходном наборе.

Как уже упоминалось в комментариях выше, избегайте наличия каких-либо свойств или методов верхнего уровня в тестовом источнике, чтобы предотвратить компилятор Kotlin от создания этого класса пакета в тестовом выходном каталоге.

+0

Спасибо. Есть еще одно обходное решение, которое следует из того, что вы сказали, я разместил его как еще один ответ. – hotkey

+0

Еще одно примечание к этому решению; по крайней мере, в Gradle, вам нужно запустить чистую сборку, или тестовый бегун все равно найдет сгенерированный класс пакета. –

1

В дополнение к тому, что было предложено ранее, я нашел другое обходное решение: если вам нужны функции или свойства на уровне пакета в test, просто переместите тесты в другой пакет, например. в ваших источниках тестов:

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

, а затем сделать

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

, который все из основного пакета. Это заставит компилятора Kotlin генерировать два не конфликтующих класса пакета, поэтому оба могут иметь глобальных членов.