2015-05-25 23 views
7

是否可以在不同的源代碼集中使用Kotlin包函數和包屬性?當我嘗試這樣做時,我有NoSuchMethodError拋出。Kotlin:測試中的java.lang.NoSuchMethodError


我有科特林代碼,並在兩份sourcesets,maintest搖籃工程。 在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創建一個名爲$ {packagename} Package的java類,其中的屬性和方法實現爲靜態方法和變量。對於多個源集,java類將創建兩次,每個源集一次。你的問題是測試源集「包類」隱藏了在主源集中編譯的類。

如上述註釋中所述,避免在測試源集中包含任何頂級屬性或方法,以防止Kotlin編譯器在測試輸出目錄中創建該包類。

+0

謝謝。還有一種解決方法是根據您所說的,我將其作爲另一個答案發布。 – hotkey

+0

這個解決方案的另一個方面說明;至少在Gradle中,您需要運行一個乾淨的構建,否則測試運行器仍然會找到生成的Package類。 –

1

除了之前的建議,我還發現了另一個解決方法:如果您需要軟件包級功能或test中的屬性,只需將測試移動到不同的軟件包,例如,在您的測試來源:

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

,然後做

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

這是從你的主包的一切。這將使Kotlin compliler生成兩個無衝突的Package類,因此兩者都可以擁有全局成員。

相關問題