ScalaTest - 编写自定义匹配器
我遇到了一个问题,同时写NodeSeq自定义匹配:ScalaTest - 编写自定义匹配器
private def matchXML(expected: NodeSeq) = new Matcher[NodeSeq] {
def apply(left: NodeSeq): MatchResult = MatchResult(left xml_== expected,
"XML structure was not the same (watch spaces in tag texts)",
"XML messages were equal")
}
这将编译,但下面的代码:
val expected : NodeSeq = ...
val xml : NodeSeq = ...
xml should matchXML(expected)
原因:
error: overloaded method value should with alternatives:
(beWord: XMLStripDecoratorTests.this.BeWord)XMLStripDecoratorTests.this.ResultOfBeWordForAnyRef[scala.collection.GenSeq[scala.xml.Node]] <and>
(notWord: XMLStripDecoratorTests.this.NotWord)XMLStripDecoratorTests.this.ResultOfNotWordForAnyRef[scala.collection.GenSeq[scala.xml.Node]] <and>
(haveWord: XMLStripDecoratorTests.this.HaveWord)XMLStripDecoratorTests.this.ResultOfHaveWordForSeq[scala.xml.Node] <and>
(rightMatcher: org.scalatest.matchers.Matcher[scala.collection.GenSeq[scala.xml.Node]])Unit
cannot be applied to (org.scalatest.matchers.Matcher[scala.xml.NodeSeq])
xml should (matchXML(expected))
任何想法是什么意思?
为什么这个不能进行类型检查:
类型检查工作以下面的方式。
xml.should(matchXML(expected))
- 因为该方法
should
不是NodeSeq
的一部分,该编译器试图找到一个xml
implicit conversion到ShouldMatcher
。 书“编程在斯卡拉”规定,这样的隐式转换应该是最具体:
“上通过的Scala 2.7,这是故事的结尾每当应用 多个隐式转换,编译器。拒绝在它们之间选择 ...... Scala 2.8放宽了这个规则如果其中一个可用的 转换比其他转换更严格,那么 编译器将选择更具体的转换......一个隐式转换 如果满足以下条件之一,则比另一个更具体:前者的参数类型为 后者的ubtype。 ..”
-
因为
NodeSeq
延伸Seq[Node]
,下面的函数,因此convertToSeqShouldWrapper[T](o : scala.GenSeq[T]) : SeqShouldWrapper[T]
是所有其他人之间最特殊的一个。
改写程序如:
`convertToSeqShouldWrapper(xml).should(matchXML(expected))`
其中convertToSeqShouldWrapper(xml)
是SeqShouldWrapper[T]
其中T = GenSeq[Node]
。
来自SeqShouldWrapper
的方法should
接受Matcher[T]
,该函数是T => MatchResult
类型的函数。因此,它接受Matcher[GenSeq[Node]]
。
因为T
出现在箭头的左侧,匹配器不是covariant在T
,但是是逆变。A NodeSeq
是GenSeq[Node]
,所以Matcher[GenSeq[Node]]
是Matcher[NodeSeq]
,而不是相反。这解释了上述错误,其中方法should
不能接受Matcher[NodeSeq]
并且需要Matcher[GenSeq[Node]]
。
2解决方案
- 替换的
NodeSeq
所有实例GenSeq[Node]
,这样的类型匹配随处可见。 -
或者,用转换函数明确地包装xml。
convertToAnyShouldWrapper(xml).should(matchXML(expected))
这对我来说就像你的matchXML
方法不在范围内。
即使matchXML在范围内,我也得到了同样的错误。 – 2013-05-06 09:23:43
什么是NodeSeq的定义是什么? – 2013-05-02 15:44:12
@MikaëlMayer我假设'scala.xml.NodeSeq' – gzm0 2013-05-02 15:49:47