在Scala中记录单元测试名称

时间:2016-03-22 10:51:21

标签: scala junit

我想自动在Scala中记录单元测试名称。 org.junit.rules.TestName的解决方案在Java中运行良好,但在Scala中运行不正常。

请考虑以下代码段:

import org.junit._
import org.junit.rules.TestName

class ScalaUnitTestExample {
    @Rule val testName = new TestName

    @Before def printTestCaseNameBefore() {
        print("\nStart of test case " + testName.getMethodName)
    }

    @After def printTestCaseNameAfter() {
        print("\nEnd of test case " + testName.getMethodName)
    }

    @Test
    def checkAddition() {
        Assert.assertEquals(5, 2 + 3)
    }

    @Test
    def checkMultiplication() {
        Assert.assertEquals(6, 2 * 3)
    }
}

它编译得很好,但在运行时我收到以下错误消息:

There was 1 failure:
1) initializationError(ScalaUnitTestExample)
java.lang.Exception: The @Rule 'testName' must be public.
        at org.junit.internal.runners.rules.RuleFieldValidator.addError(RuleFieldValidator.java:90)
        (...)
        at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

FAILURES!!!
Tests run: 1,  Failures: 1

Java版本按预期工作。

我已经尝试了以下内容(根据Using JUnit @Rule with ScalaTest (e.g. TemporaryFolder)):

val _testName = new TestName
@Rule def testName = _testName

但这并没有真正帮助。在此版本中,测试用例会运行,但{testName}结果始终为{null}。

Scala中的默认访问规则是公开的,因此没有public个关键字。另一方面,JUnit框架似乎认为它是非公开的。

有谁知道如何克服这个问题?另一个类似的解决方案也没问题!谢谢!

3 个答案:

答案 0 :(得分:1)

如您所知,scala默认访问规则是公开的,但scala是一个技巧,该字段是私有的,它会生成getter和setter,这就是@Rule在您的代码中不起作用的原因。

您可以使用

使其正常工作
import org.junit._
import org.junit.rules.TestName


    class ScalaUnitTestExample {
      var _testName: TestName = new TestName

      @Rule
      def testName = _testName
      def testName_=(aTestName: TestName) {_testName = aTestName}

      @Before def printTestCaseNameBefore() {
        print("\nStart of test case " + testName.getMethodName)
      }

      @After def printTestCaseNameAfter() {
        print("\nEnd of test case " + testName.getMethodName)
      }

      @Test
      def checkAddition() {
        Assert.assertEquals(5, 2 + 3)
      }

      @Test
      def checkMultiplication() {
        Assert.assertEquals(6, 2 * 3)
      }
    }

enter image description here

无论如何使用ScalaTest或Specs2会让您的生活更轻松。

答案 1 :(得分:0)

解决方案(轻松破解):将方法名称逻辑放入用Java编写的基类中。 Java源代码(UnitTestBase.java):

import org.junit.*;
import org.junit.rules.TestName;

public class UnitTestBase {
    @Rule public TestName testName = new TestName();

    @Before public void printTestCaseNameBefore() {
        System.out.println("Start of test case " + testName.getMethodName());
    }

    @After public void printTestCaseNameAfter() {
        System.out.println("End of test case " + testName.getMethodName());
    }
}

Scala源代码(ScalaUnitTestExample.scala):

import org.junit._

class ScalaUnitTestExample extends UnitTestBase {
    @Test
    def checkAddition() {
        Assert.assertEquals(5, 2 + 3)
    }

    @Test
    def checkMultiplication() {
        Assert.assertEquals(6, 2 * 3)
    }
}

编译:

scalac -cp .;junit-4.9.jar UnitTestBase.java ScalaUnitTestExample.scala

执行命令

scala -cp .;junit-4.9.jar org.junit.runner.JUnitCore ScalaUnitTestExample

结果:

JUnit version 4.9
.Start of test case checkMultiplication
End of test case checkMultiplication
.Start of test case checkAddition
End of test case checkAddition

Time: 0,005

OK (2 tests)

答案 2 :(得分:0)

使用JUnit 4.12,我使用了@Jonas Anso的解决方案,并且与该版本一起使用,在4.8和4.10中不起作用。 我们必须在方法而不是字段上设置@Rule,似乎在4.8和4.10中将其忽略。 而且只需要吸气剂。