为简单起见,假设我们有一个称为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编写的。
答案 0 :(得分:2)
让您的方法故意抛出是一个坏主意,而且绝对不符合FP的精神。在具有失败能力的方法的类型签名中捕获失败可能更好。
private def listTail(ls: List[Int]): Try[List[Int]] = Try {
ls.tail
}
现在您的用户知道这将返回Success
或Failure
,并且没有魔术堆栈展开。这样已经可以更轻松地测试该方法。
您还可以通过这种公式摆脱使用简单的def safeTailList(ls: List[Int]) = listTail(l).getOrElse(Nil)
进行模式匹配的过程–相当不错!
如果要对此进行测试,可以将其打包并进行相应的测试。
更好的主意是重新考虑您的算法。有内置安全尾巴的机械:
def safeTailList(ls: List[Int]) = ls.drop(1)
答案 1 :(得分:0)
实际上是相反的情况:通常,您不希望测试私有方法,而只是测试公共方法,因为只要它们按承诺工作,它们就是定义您与外界交互的方法,谁在乎您的私有方法做什么,那只是实现细节。
因此,最重要的是-仅测试您的safeListTail
,仅此而已,无需分别测试内部实现。
顺便说一句,您不需要那里的match
:Try(listTail(ls)).getOrElse(handleEmptyList(ls))
等同于那里的东西……这实际上不是一个好主意,因为它吞没了其他异常,而不仅仅是当列表为空时抛出的一个更好的方法实际上是恢复match
但摆脱Try
:
ls match {
case Nil => handleEmptyList(ls)
case _ => listTail(ls)
}