如何使用 Junit 4 和 Scala 测试异常?

How to test exception with Junit 4 and Scala?

我想测试以下功能:

   def filterFoo(FooColumnName: String, Foo: Seq[Any]): DataFrame = {
      /* validate input parameters */
      require(Option(FooColumnName).isDefined)
      require(Option(Foo).isDefined)
      require(df.columns.contains(FooColumnName))

      df.filter(col(FooColumnName).isin(Foo:_*))

我写了下面的测试:

  @Test(expected = classOf[IllegalArgumentException])
  def testFilterFoorWrongColumnName(): Unit ={

    val df = data.toDF(columns:_*)
    df.filterFoo(FooColumnName = "foo", Foo = competitors)

  }

如果数据框中不存在 FooColumnName,它将抛出 IllegalArgumentException。我收到此异常,但因此未通过测试。当我 运行 测试时出现此错误:

java.lang.IllegalArgumentException: requirement failed

诀窍是将异常具体化为一个值,谢天谢地,这是 Scala 中非常惯用的东西。 scala.util.Try 在标准库中,对此特别有用:

import scala.util.{ Failure, Success, Try }

@Test(expected = classOf[IllegalArgumentException])
def testFilterFoorWrongColumnName(): Unit ={
  val df = data.toDF(columns:_*)
  val attempt = Try {  // note the capital T, this is not the keyword try...
    df.filterFoo(FooColumnName = "foo", Foo = competitors)
  }

  // apologies, I don't know JUnit at all...
  attempt match {
    case _: Success =>
      failTheTest  // should have been a failure

    case Failure(ex) =>  // ex is the thrown exception
      // can check that the exception is an IllegalArgumentException or whatever
      doChecksOnException
  }
}

它的工作原理是 Try[T]Success 包装 TFailure 包装 ThrowableTry { } 将代码包装在 try 块中并捕获异常;如果它是 NonFatal 异常,则该异常进入 Failure。使用 Try 还有其他一些很好的理由(它有一些很好的组合属性),但这些不在这个答案的范围内。