我该如何在Scala中使用JUnit的ExpectedException?

6
我希望能够在Scala中使用JUnit 4.7的ExpectedException @Rule,但它似乎无法捕获任何异常:
import org.junit._

class ExceptionsHappen {

  @Rule 
  def thrown = rules.ExpectedException.none

  @Test
  def badInt: Unit = {
    thrown.expect(classOf[NumberFormatException])
    Integer.parseInt("one")
  }
}

这仍然失败并显示 NumberFormatException

6个回答

10

为了让这个在Scala中使用JUnit 4.11的方法生效,你应该元注释(meta-annotate)你的注释,以便注释只应用于(合成的)synthetic getter方法,而不是基础字段:

import org.junit._
import scala.annotation.meta.getter

class ExceptionsHappen {

  @(Rule @getter)
  var thrown = rules.ExpectedException.none

  @Test
  def badInt: Unit = {
    thrown.expect(classOf[NumberFormatException])
    Integer.parseInt("one")
  }
}

8

编辑:在JUnit 4.11发布后,您现在可以使用@Rule注释一个方法。

您将使用它如下:

private TemporaryFolder folder = new TemporaryFolder();

@Rule
public TemporaryFolder getFolder() {
    return folder;
}

对于早期版本的JUnit,见下面的答案。

--

不,你不能直接从Scala中使用它。字段需要是公共的和非静态的。来自org.junit.Rule

public @interface Rule:注释包含规则的字段。这样的字段必须是公共的、非静态的,并且是TestRule的子类型。

在Scala中,您无法声明公共字段。所有字段都是私有的,并通过访问器进行访问。请参阅此问题的答案

另外,JUnit已经有一个增强请求(仍然处于打开状态):

扩展规则以支持@Rule public MethodRule someRule() { return new SomeRule(); }

另一种选择是允许非公共字段,但是这已经被拒绝:允许在非公共字段上使用@Rule注释

因此,您的选项是:

  1. 克隆junit,并实现第一个建议,该方法,并提交拉取请求
  2. 从实现@Rule的java类中扩展Scala类

-

public class ExpectedExceptionTest {
    @Rule
    public ExpectedException thrown = ExpectedException.none();
}

然后从那个类继承:

class ExceptionsHappen extends ExpectedExceptionTest {

  @Test
  def badInt: Unit = {
    thrown.expect(classOf[NumberFormatException])
    Integer.parseInt("one")
  }
}

正常运行。


2
为了清晰起见:它现在可以在Scala上运行(但只能使用方法@Rule def myRule = ...,而不能使用属性,如@Rule val myRule = ...)。 - Juh_

1
作为一个 Scala 的新手,我只是使用了一个非常简单的解决方案:显式地捕获异常并在您期望的异常未被抛出时失败。
下面是一个示例框架:
try {
  *your code that should throw an exception*
  fail("Did not generate *the.Exception.you.expect*")
} catch {
  case t: *the.Exception.you.expect* => // do nothing, it's expected :)
}

0

我仍在使用JUnit 4,并发现@Juh_的评论很有指导意义。这在Scala 2.11.0中有效。

import org.junit.rules.ExpectedException
import org.junit.{Rule, Test}

import scala.reflect.{ClassTag, classTag}

class DeleteMe {

  object Thrower {
    def throwException[R <: Throwable: ClassTag](message: String): Unit = {
      throw classTag[R].runtimeClass.getConstructor(classOf[String]).newInstance(message).asInstanceOf[R]
    }
  }

  @Rule
  def exceptionRule:ExpectedException = ExpectedException.none()

  @Test(expected = classOf[Exception])
  def checkConversionExceptions = {
    val myMessage = "My Message"
    exceptionRule.expectMessage(myMessage)
    Thrower.throwException[Exception](myMessage)
    ()
  }
}

0

由于我手头没有适当的设置,不知道JUnit规则并且没有测试它,因此我冒险建议将抛出的内容转换为值(val)。 我猜它是一个成员变量,它被初始化为某些值,然后获得某些状态,然后其他一些机制将其状态与某些东西进行比较。你总是创建新的实例并且忘记了期望的结果。


0
如果Scala有类似静态导入的功能,那么catch-exception是JUnit 4.7的ExpectedException @Rule的替代品。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接