代码之家  ›  专栏  ›  技术社区  ›  outis

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

  •  1
  • outis  · 技术社区  · 7 年前

    概述

    应用 @DataPoint @DataPoints 到Kotlin类中的属性会导致“DataPoint字段samples must be public”错误。

    说明

    青少年使用理论 @数据点 @数据点 用于标记样本数据的注释,这些样本数据被收集并传递给可以将其作为参数的各个测试。当这些注释应用于Kotlin属性(这些属性也必须在@JvmStatic中注释并在伴随对象中声明)时,测试用例失败,并出现错误“DataPoint field samples must be public”。默认情况下,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'
        // ...
    }
    

    其他系统信息

    • 安卓工作室3.1.3
    • 等级4.4
    • Android gradle插件3.1.3
    2 回复  |  直到 7 年前
        1
  •  2
  •   Kiskae    7 年前

    这可能是因为Kotlin不知道字节码中的注释应该放在哪里。这意味着实际代码如下:

    private static List<Integer> samples = ....
    
    @DataPoints
    public static List<Integer> getSamples() {
        return this.samples;
    }
    

    更换 @JvmStatic 具有 @JvmField 应该使它生成正确的代码。如果您使用IntelliJ,您可以始终使用 Inspect Kotlin Bytecode 命令检查正在生成的代码。

        2
  •  0
  •   outis    7 年前

    在幕后,Kotlin的公共属性有一个私有的支持域和公共访问器。在JavaSead(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
      )
      

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