在Kotlin中使用JUnit 4理论时出现“ DataPoint字段样本必须是公共的”错误

时间:2018-08-05 21:53:52

标签: kotlin junit4

概述

@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'
    // ...
}

其他系统信息

  • Android Studio 3.1.3
  • 4.4级
  • Android gradle插件3.1.3

2 个答案:

答案 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属性不存在。相反,必须显式使用字段和访问器方法。

由于将批注应用于(私有)字段而不是(公共)访问器,因此出现错误。

有两种解决方法:

  1. @DataPoints注释应用于属性的getter:

    @JvmStatic
    val samples = listOf(
        -8, -1, 0, 1, 2, 4, 8
    ) @DataPoints get
    

    这只会计算一次表达式。

  2. 将数据点声明为方法而不是属性:

    @JvmStatic
    @DataPoints
    fun samples = listOf(
        -8, -1, 0, 1, 2, 4, 8
    )
    

    由于数据点源是一个函数,因此每次检索它们(可能不会很多次;我对Theories的内部知识都不熟悉)时,都会重新计算该表达式。