【问题标题】:zio assert subtype of algebraic data typezio 断言代数数据类型的子类型
【发布时间】:2021-04-09 20:10:39
【问题描述】:
给定代数数据类型
sealed trait Result
case object Success extends Result
case class MyFailure(details: String) extends Result
如何在 zio-test 中断言特定值是 Failure 并且其详细信息包含特定子字符串?
例如如何断言r 下面是一个失败并且带有"mana" 子字符串?
val r: Result = MyFailure("not enough mana")
【问题讨论】:
标签:
scala
unit-testing
zio
zio-test
【解决方案1】:
假设结果是由一个 effect 产生的(也就是说,它被 ZIO 包裹了),你可以使用mapError 在失败的情况下使用details,然后使用assertM 和fails(containsString) 进行有效断言:
testM("effectfully") {
val r = ZIO.fail(MyFailure("not enough mana")).mapError(_.details)
assertM(r.run)(fails(containsString("mana")))
}
【解决方案2】:
isCase 可以实现
截图:
/**
* Makes a new assertion that requires the sum type be a specified term.
*
* {{{
* isCase("Some", Some.unapply, anything)
* }}}
*/
def isCase[Sum, Proj](
termName: String,
term: Sum => Option[Proj],
assertion: Assertion[Proj]
)
还有我的(可能不是理想的)解决方案:
sealed trait Result
case object Success extends Result
case class MyFailure(details: String) extends Result
val r: Result = MyFailure("not enought mana")
test("mana") {
assert(r)(
isCase[Result, String](
"details",
{
case MyFailure(details) => Some(details)
case _ => None
},
containsString("mana"))
)
}
或者,可以创建一个辅助函数并将其用于这种情况:
def matches[A](mf: PartialFunction[A, Boolean]): Assertion[A] =
Assertion.assertion("matches")() {
a => mf.orElse[A, Boolean]({ case _ => false })(a)
}
现在测试可能如下所示:
assert(r)(
matches {
case MyFailure(d) => d.contains("mana")
}
)