繁体   English   中英

使用尝试,成功,失败的Scala中的单元测试策略

[英]Unit testing strategy in Scala with Try, Success, Failure

为了简单起见,假设我们有一个名为listTail的方法,该方法以以下方式定义:

private def listTail(ls: List[Int]): List[Int] = {
 ls.tail
}

我们还有一个方法可以在列表为空时处理异常。

private def handleEmptyList(ls: List[Int]): List[Int] = {
 if(ls.isEmpty) List.empty[Int]
}

现在,我想创建一个安全版本的listTail方法,该方法同时使用两种方法:

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

def safeListTail(ls: List[Int]): List[Int] = {
 val tryTail: Try[List[Int]] = Try(listTail(ls))
 tryTail match {
   case Success(list) => list
   case Failure(_) => handleEmptyList(ls)
 }
}

我的问题是,如果两个私有方法都已经过测试,那么我也应该测试安全方法吗? 如果是的话,怎么办? 我当时只是想检查是否根据输入内容执行了模式匹配案例。 也就是说,当我们遇到“失败”情况时,将执行handleEmptyList方法。 但是我现在知道如何检查这一点。

还是我需要重构代码,并将所有内容放在一个方法中? 即使也许我的私有方法比示例中的复杂得多。

我的测试是使用ScalaTest编写的。

允许您的方法故意抛出是一个坏主意,并且绝对不符合FP的精神。 在具有失败能力的方法的类型签名中捕获失败可能更好。

private def listTail(ls: List[Int]): Try[List[Int]] = Try {
  ls.tail
}

现在,您的用户知道这将返回SuccessFailure并且没有魔术堆栈展开。 这已经使测试该方法更加容易。

您也可以使用此公式使用简单的def safeTailList(ls: List[Int]) = listTail(l).getOrElse(Nil)摆脱模式匹配-很好!

如果要对此进行测试,可以将其打包,然后进行相应的测试。

更好的主意是重新考虑您的算法。 有使内置安全尾巴成为可能的机器:

def safeTailList(ls: List[Int]) = ls.drop(1)

实际上,这是另一回事:通常,您不想测试私有方法,仅想测试公共方法,因为只要它们按承诺工作,它们便会定义您与外界的交互,他们会在乎什么?您的私有方法就可以了,这只是实现细节。

因此,最重要的是-只需测试您的safeListTail ,仅此而已,无需分别测试内部实现。

顺便说一句,您不需要那里的matchTry(listTail(ls)).getOrElse(handleEmptyList(ls))等同于您在那里...实际上不是一个好主意,因为它吞没了其他异常,而不仅仅是在列表为空时抛出的那个,一种更好的方法实际上是恢复match但摆脱Try

  ls match {
     case Nil => handleEmptyList(ls)
     case _ => listTail(ls)
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM