Scala学习笔记之测试异常

年前整理过一篇 JUnit 4 如何正确测试异常,类似的问题:如何在 Scala 中测试异常呢?因 Scala 可以完全采用 JUnit 测试用例的风格,所以当然可以运用 Java 的三种方式来测试异常,即

try { 待测试代码; fail() } catch(某种异常) {断言}

@

Test(expected = Exception.class)

@Rule

回到 Scala 中来,我并不那么情愿在 Scala 中使用 JUnit 的 @Test def testMethod() 这样的测试方法风格,而多少采用 BDD 或者叫更 DSL 的风格。

那看看我们 Scala 有些什么独到的异常测试方法

一: intercept

import org.scalatest.FlatSpec
 
class ScalaExceptionTest extends FlatSpec {
  "An empty Set" should "produce NoSuchElementException when head is invoked" in {
    intercept[NoSuchElementException] {
      Set.empty.head
    }
  }
}
测试结果
scala-intercept

打开 intercept 方法的源码,其实这就是 try-catch 的方式。intercept 方法的源码如下:

def intercept[T <: AnyRef](f: => Any)(implicit manifest: Manifest[T]): T = {
    val clazz = manifest.erasure.asInstanceOf[Class[T]]
    val caught = try {
      f
      None
    }
    catch {
      case u: Throwable => {
        if (!clazz.isAssignableFrom(u.getClass)) {
          val s = Resources("wrongException", clazz.getName, u.getClass.getName)
          throw newAssertionFailedException(Some(s), Some(u), 4)
        }
        else {
          Some(u)
        }
      }
    }
    caught match {
      case None =>
        val message = Resources("exceptionExpected", clazz.getName)
        throw newAssertionFailedException(Some(message), None, 4)
      case Some(e) => e.asInstanceOf[T] // I know this cast will succeed, becuase isAssignableFrom succeeded above
    }
  }
intercept() 方法返回的是当前抛出的异常,所以可以对它的返回值进行更详细的断言
val s = "hi"
val thrown = intercept[IndexOutOfBoundsException] {
  s.charAt(-1)
}
assert(thrown.getMessage === "String index out of range: -1")

二:thrownBy

import org.scalatest.{MustMatchers, WordSpec}
 
class ScalaExceptionTest extends WordSpec with MustMatchers{
 
  "An empty Set produce NoSuchElementException when head is invoked" in {
    a[NoSuchElementException] must be thrownBy {
      Set.empty.head
    }
  }
}

执行之后的描述信息是
[info] ScalaExceptionTest:
[info] - An empty Set produce NoSuchElementException when head is invoked
[info] ScalaTest
[info] Run completed in 1 second, 247 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.

也就是 in {} 中的执行代码从描述信息并没有帮助,虽然它看上去很美。

thrownBy 的实现方式与 intercept 是一样的。

第一代 specs 可以用 throwA/throwAn 方法,现在转到  specs2 了,specs 已停止开发,从 https://code.google.com/p/specs/ 找了个例子:

"A full stack"->-(fullStack) should {

  behave like "A non-empty stack below full capacity"

  "throw an exception when sent #push" in {

    stack.push(11) must throwAn[Error]

  }

}

Scala 使用 Java 的风格与 JUnit 4 如何正确测试异常 中的用法基本一致的。try-catch 方式也只是存在语法上的差异

import org.junit.Assert._

import org.junit.Test

 

class ScalaExceptionTest{

 

  @Test def testInvokeHeadOnEmptySet: Unit = {

    try {

      Set.empty.head

      fail("nothing thrown")

    } catch {

      case err: NoSuchElementException => // test success

      case t: Throwable => fail(s"caught ${t.getClass.getName} instead of NoSuchElementException")

    }

  }

}

总之,Scala 风格的异常测试也就是 intercept 和 thrownBy 两种。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索异常
, class
, 测试
, junit
scala
,以便于您获取更多的相关知识。

时间: 2024-10-26 07:02:50

Scala学习笔记之测试异常的相关文章

机器学习(三)--- scala学习笔记

 Scala是一门多范式的编程语言,一种类似Java的编程语言,设计初衷是实现可伸缩的语言.并集成面向对象编程和函数式编程的各种特性.    Spark是UC Berkeley AMP lab所开源的类Hadoop MapReduce的通用并行框架,Spark,拥有Hadoop MapReduce所具有的优点:但不同于MapReduce的是Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的MapReduce的算法. 一.sca

scala 学习笔记(04) OOP(上)主从构造器/私有属性/伴生对象(单例静态类)/apply方法/嵌套类

一.主从构造器 java中构造函数没有主.从之分,只有构造器重载,但在scala中,每个类都有一个主构造器,在定义class时,如果啥也没写,默认有一个xxx()的主构造器 class Person { var name: String = _ /** * 从构造器 * @param name */ def this(name: String) = { this //注意:从构造器,必须先调用主构造器 this.name = name; } override def toString = { "

Nodejs学习笔记之测试驱动_node.js

分享第二章,关于测试驱动.这里的测试主要针对Web后端的测试 -- 你为什么要写测试用例(即测试用例的完善是否是浪费时间),如何完善你的测试用例,代码设计如何简化测试用例的书写,以及一些后期的构想. 1. 你为什么要写测试用例 这个习惯通常会被认为是一种耽误开发进度的行为,你需要花费几乎和开发代码相同的时间来逐步完善你的测试用例.但是在开发过程中,在开发完成一段代码后如果负责任而不是说完全把问题交给测试人员去发现的话,这个时候通常都会去做一些手动的测试.例如: 在代码中执行某些方法,查看输出的值

Scala 学习笔记(转)

问题描述 scala是以实现scaleablelanguage为初衷设计出来的一门语言.官方中,称它是object-orientedlanguage和functionallanguage的混合式语言.并且,scala可以和java程序无缝拼接,因为scala文件编译后也是成为.class文件,并且在JVM上运行.不过,我更关心的是它的scaleable(扩展性).一门语言到底怎样才算有扩展性呢?对语言而言什么是它的扩展性呢?个人拙见,认为语言的扩展性可能包括两个方面:1.语言本身的扩展性2.由此

[Scala]Scala学习笔记七正则表达式

1. Regex对象 我们可以使用scala.util.matching.Regex类使用正则表达式.要构造一个Regex对象,使用String类的r方法即可: val numPattern = "[0-9]+".r 如果正则表达式包含反斜杠或引号的话,那么最好使用"原始"字符串语法"""...""": val positiveNumPattern = """^[1-9]\d*

Scala学习笔记

1类型自动匹配(模式匹配) 2函数是有值的(匿名函数是函数的常态) 递归函数需要指定返回值 3.内部类隶属于外部类的实例本身,而java内部类属于外部类,对外部类的依赖路径依赖 4.object类似于java中的静态内部类 里面的所有成员都是静态的,适用于配置文件 静态都是用来修饰类的内部成员的.比如静态方法.静态成员变量.它唯一的作用就是随着类的加载(而不是随着对象的产生)而产生,以致可以用类名+静态成员名直接获得.这样静态内部类就可以理解了,它可以直接被用 外部类名+内部类名 获得. 5.同

scala 学习笔记(02) 元组Tuple、数组Array、Map、文件读写、网页抓取示例

package yjmyzz import java.io.PrintWriter import java.util.Date import scala.io.Source object ScalaApp02 { def main(args: Array[String]) { tupleDemo println mapDemo println arrayDemo println fileWriteAndRead println(getUrlContent("http://www.cnblogs.

scala 学习笔记(05) OOP(中)灵活的trait

trait -- 不仅仅只是接口! 接上回继续,scala是一个非常有想法的语言,从接口的设计上就可以发现它的与众不同.scala中与java的接口最接近的概念是trait,见下面的代码: package yjmyzz object App { def main(args: Array[String]) { val bird = Bird("pigeon") bird.fly println(bird.isInstanceOf[Bird]) //true println(bird.is

scala 学习笔记(01) 函数定义、分支、循环、异常处理、递归

package yjmyzz import scala.io.StdIn object ScalaApp { def main(args: Array[String]) { println("please input something,press Enter to exit:") //每一行最后加不加分号都可以 readKeyboard //注:无参数的函数调用,加不加括号都行 println(add(1, 2) + "\n------\n") println(d