【问题标题】:JUnit 5: How to assert an exception is thrown in Scala?JUnit 5:如何断言在 Scala 中引发了异常?
【发布时间】:2019-01-28 22:53:13
【问题描述】:

版本:

jdk1.8.0 斯卡拉:2.11

<properties>
 <junit.jupiter.version>5.2.0</junit.jupiter.version>
  <junit.platform.version>1.2.0</junit.platform.version>
</properties>
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-all</artifactId>
  <version>1.9.5</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-api</artifactId>
  <version>${junit.jupiter.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-engine</artifactId>
  <version>${junit.jupiter.version}</version>
  <scope>test</scope>
</dependency>

我正在关注这个question,它展示了如何在 java 中使用 junit 5 断言异常。

当我尝试在 scala 中做同样的事情时:

val closureContainingCodeToTest = () -> myClass.myMethod(data)   // or     val closureContainingCodeToTest = () => myClass.myMethod(data)
assertThrows(classOf[MyException], closureContainingCodeToTest)

我收到此错误:

 Error:(89, 48) type mismatch;
 found   : () => Unit
 required: org.junit.jupiter.api.function.Executable
    assertThrows(classOf[MyException], closureContainingCodeToTest)

这可能是一个非常简单的问题,但我找不到如何在 Scala 中为 Java Executable 对象创建 Scala 闭包。

编辑:

添加一个简单的完整测试:

package com.my.lib

import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.function.Executable

class myTest {

  @Test
  def myTest = {
    val closureContainingCodeToTest:Executable = () => throw new RuntimeException()
    assertThrows(classOf[RuntimeException], closureContainingCodeToTest)
  }
}

我收到以下错误:

Error:(11, 53) type mismatch;
 found   : () => Nothing
 required: org.junit.jupiter.api.function.Executable
    val closureContainingCodeToTest:Executable = () => throw new RuntimeException()

【问题讨论】:

  • 您的代码为我编译并运行 - 在我将 Unit 返回类型添加到 myTest 之后。如果您使用的是 IDE,那么我认为这只是需要清理/重建项目以考虑到您添加的Executable。如果我从closureContainingCodeToTest 中删除Executable,我可以重新创建您的错误,但它会在重新添加并清理/重建后编译。
  • @Nio 这很奇怪,即使从终端使用mvn clean compile test,我也会遇到同样的错误。

标签: java scala unit-testing junit junit5


【解决方案1】:

如果我们想用 Junit 5 风格来做 - 你可以像下面的代码那样做:

import org.junit.jupiter.api.{DisplayName, Test}
import org.junit.runner.RunWith
import org.scalatest.junit.{JUnitRunner, JUnitSuite}

@RunWith(classOf[JUnitRunner])
class Junit_5_Test extends JUnitSuite{

  object ExceptionTest {
    @throws(classOf[RuntimeException])
    def throwRunEx = throw new RuntimeException
  }

  @Test
  @DisplayName("Example with JUnitSuite")
  def throwsExceptionWhenCalled_With_JUnitSuite() {
    import ExceptionTest._
    assertThrows[RuntimeException]{ throwRunEx}
  }

}

要这样做 - 您需要将其包含在您的 build.sbt 中:

"org.junit.jupiter" % "junit-jupiter-api" % "5.2.0" % Test,
 "org.scalatest" %% "scalatest" % "3.2.0-SNAP10" % Test

【讨论】:

    【解决方案2】:

    您可以通过明确说明闭包的返回类型,即强制将函数类型 () =&gt; myClass.myMethod(data) 转换为 Executable。添加Executable

    import org.junit.jupiter.api.Assertions.assertThrows
    import org.junit.jupiter.api.Test
    import org.junit.jupiter.api.function.Executable
    
    class MyClassTests {
    
      val closureContainingCodeToTest: Executable = () => (new MyClass).myMethod(data)
    
      @Test
      def throwsExceptionWhenCalled(): Unit = {
        assertThrows(classOf[MyException], closureContainingCodeToTest)
      }
    
    }
    

    或者,如果你内联它,那么你甚至不需要显式。

    import org.junit.jupiter.api.Assertions.assertThrows
    import org.junit.jupiter.api.Test
    
    class MyClassTests {
    
      @Test
      def throwsExceptionWhenCalled(): Unit = {
        assertThrows(classOf[MyException], () => (new MyClass).myMethod(data))
      }
    
    }
    

    另请注意,您的测试方法需要返回 Unit 否则它们将永远不会运行。

    【讨论】:

    • 谢谢,但是这些我已经尝试过并且给出了同样的错误。我也有_execute 方法,不要与Executable 接口的execute 方法混淆。
    • 不用担心。这很奇怪,它的编译/运行对我来说没问题。也许发布您的完整代码?你在使用 junit.jupiter 5.2.0 吗?
    • 是的,junit.jupiter 5.2.0 我已经用一个简单的例子更新了这个问题。
    【解决方案3】:

    为了建立之前的答案,我想编写多行测试代码,而不是只调用 MyClass.myMethod(data)

    import org.junit.jupiter.api.Assertions.assertThrows
    import org.junit.jupiter.api.Test
    import org.junit.jupiter.api.function.Executable
    
    class MyClassTest {
    
      @Test
      def throwsExceptionWhenCalled(): Unit = {
        assertThrows(classOf[MyException], new Executable {
          override def execute(): Unit = {
            val data = generateBadData()
            new MyClass().myMethod(data) // throws MyException
          }
        })
      }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2017-03-09
      • 2010-09-14
      • 2020-04-20
      • 2014-06-13
      • 2023-03-03
      • 1970-01-01
      • 2023-03-15
      相关资源
      最近更新 更多