2013-05-02 67 views
6

我遇到了一個問題,同時寫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)) 

任何想法是什麼意思?

+0

什麼是NodeSeq的定義是什麼? – 2013-05-02 15:44:12

+0

@MikaëlMayer我假設'scala.xml.NodeSeq' – gzm0 2013-05-02 15:49:47

回答

7

爲什麼這個不能進行類型檢查:

類型檢查工作以下面的方式。

xml.should(matchXML(expected)) 
  • 因爲該方法should不是NodeSeq的一部分,該編譯器試圖找到一個xmlimplicit conversionShouldMatcher。 書「編程在斯卡拉」規定,這樣的隱式轉換應該是最具體:

「上通過的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出現在箭頭的左側,匹配器不是covariantT,但是是逆變。A NodeSeqGenSeq[Node],所以Matcher[GenSeq[Node]]Matcher[NodeSeq],而不是相反。這解釋了上述錯誤,其中方法should不能接受Matcher[NodeSeq]並且需要Matcher[GenSeq[Node]]

2解決方案

  • 替換的NodeSeq所有實例GenSeq[Node],這樣的類型匹配隨處可見。
  • 或者,用轉換函數明確地包裝xml。

    convertToAnyShouldWrapper(xml).should(matchXML(expected))

+0

雖然第二種解決方案起作用,但第一種解決方案(將所有內容轉換爲「Seq [Node]」)仍顯示相同的錯誤。 – HRJ 2013-08-11 14:46:22

+0

我可以通過將所有內容轉換爲GenSeq [Node]來解決這個問題。我正在使用'scalatest 2.0 M5',因此可能有所不同。 – HRJ 2013-08-11 14:50:21

+0

的確,在這個版本中,convertToSeqShouldWrapper方法的簽名是'GenSeq [T] => SeqShouldWrapper [T]'。所以我更新了我的答案。 – 2013-08-12 09:23:05

-1

這對我來說就像你的matchXML方法不在範圍內。

+0

即使matchXML在範圍內,我也得到了同樣的錯誤。 – 2013-05-06 09:23:43