将@DataPoint
或@DataPoints
应用于Kotlin类中的属性会导致“ DataPoint字段样本必须是公共的”错误。
JUnit4中的理论使用@DataPoint
和@DataPoints
批注来标记样本数据,这些样本数据被收集并传递到可以将其作为参数的单个测试中。当这些注释应用于Kotlin属性(也必须注释@JvmStatic并在伴随对象中声明)时,测试用例将失败,并出现错误“ DataPoint字段样本必须是公共的”。默认情况下,应该将Kotlin属性设为公开。而且,显式添加“ public”修饰符没有任何作用。
import org.junit.runner.RunWith
import org.junit.experimental.theories.Theories
import org.junit.experimental.theories.DataPoints
import org.junit.experimental.theories.Theory
import org.junit.Assume.*
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.*
@RunWith(Theories::class)
class SampleTheories {
companion object {
@JvmStatic
@DataPoints
public val samples = listOf(
-8, -1, 0, 1, 2, 4, 8
)
}
@Theory
fun triangleInequality(a:Int, b:Int) {
assumeThat(a, `is`(greaterThan(0)))
assumeThat(b, `is`(greaterThan(0)))
assertThat(a+b, `is`(greaterThan(a)))
assertThat(a+b, `is`(greaterThan(b)))
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.51"
// ...
testImplementation 'junit:junit:4.12'
testImplementation 'org.hamcrest:hamcrest-library:1.3'
// ...
}
答案 0 :(得分:2)
这可能是因为Kotlin不知道注释应在字节码中的何处。这意味着实际代码将类似于:
private static List<Integer> samples = ....
@DataPoints
public static List<Integer> getSamples() {
return this.samples;
}
用@JvmStatic
替换@JvmField
应该使它生成正确的代码。如果您使用的是IntelliJ,则始终可以使用Inspect Kotlin Bytecode
命令来检查正在生成的代码。
答案 1 :(得分:0)
在引擎盖下,科特林的公共财产有私人支持和公共入口。在Java方面(这是JUnit4的运行方式),Kotlin属性不存在。相反,必须显式使用字段和访问器方法。
由于将批注应用于(私有)字段而不是(公共)访问器,因此出现错误。
有两种解决方法:
将@DataPoints
注释应用于属性的getter:
@JvmStatic
val samples = listOf(
-8, -1, 0, 1, 2, 4, 8
) @DataPoints get
这只会计算一次表达式。
将数据点声明为方法而不是属性:
@JvmStatic
@DataPoints
fun samples = listOf(
-8, -1, 0, 1, 2, 4, 8
)
由于数据点源是一个函数,因此每次检索它们(可能不会很多次;我对Theories的内部知识都不熟悉)时,都会重新计算该表达式。