Specs2中beRight匹配器无类型检查:如何使用带类型检查的等价匹配器?
Specs2: 使用带类型检查的Either匹配器(基于Diffable)
你完全找对方向了——Specs2里确实有具备编译期类型检查能力的Either匹配器,就是你贴出的代码里那个带Diffable上下文绑定的right[T](t: T)重载版本,它正是beRight的类型安全等价替代。下面具体说怎么用:
为什么beRight没有类型检查?
先简单理清楚原因:
- 无参的
beRight[T]只是检查实例是否是Right,但不会在编译时约束T和实际Right的类型是否一致; - 带
ValueCheck[T]的beRight(t),如果ValueCheck的类型没有显式绑定,编译器可能不会做严格的类型校验,导致像beRight("string")匹配Right(42)这种类型不匹配的代码能通过编译,直到运行时才失败。
如何使用类型安全的right匹配器?
这个匹配器的核心是借助Diffable上下文绑定,在编译阶段就验证Either的Right部分类型和你期望的类型是否一致,用法非常直接:
基础值匹配
对于标准类型(Int、String、List等),Specs2已经默认提供了Diffable实现,直接用right(expectedValue)即可:val myEither: Either[String, Int] = Right(42) // 编译通过:类型匹配,运行时验证值是否相等 myEither must right(42) // 编译直接报错:Right的类型是Int,和传入的String不匹配 // myEither must right("42")如果编译器无法自动推断类型(比如复杂泛型场景),可以显式指定类型参数:
myEither must right[Int](42)自定义条件检查
如果你需要的不是精确值匹配,而是自定义检查逻辑,可以用带ValueCheck[T]的重载版本,同样能获得类型安全:// 编译通过:检查Right的值是否大于40 myEither must right[Int](_ > 40) // 编译报错:类型不匹配,Right是Int类型,不能用String的检查逻辑 // myEither must right[String](_.startsWith("foo"))自定义类型的
Diffable实现
如果是你自己定义的类型,只需要为它实现Diffabletrait(或者用Specs2的自动推导,比如基于Equals的默认实现),就能使用这个匹配器:case class User(id: Int, name: String) // 自定义Diffable(如果需要更友好的差异输出) implicit val userDiffable: Diffable[User] = Diffable.derived[User] val userResult: Either[Error, User] = Right(User(1, "Alice")) userResult must right(User(1, "Alice")) // 编译时类型检查,运行时对比差异
总结
核心就是用right(expectedValue)(或显式right[T](expectedValue))替代beRight,这个匹配器借助Diffable实现了编译期类型检查,完全满足你不需要must_===或beLike的诉求。
内容的提问来源于stack exchange,提问作者satyagraha
相关产品推荐
相关产品推荐

