2013-05-02 10 views
6

używam na problem podczas pisania niestandardowego dopasowywania do NodeSeq:ScalaTest - pisanie na zlecenie dopasowujące

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") 
} 

kompiluje to, ale następujący fragment kodu:

val expected : NodeSeq = ... 
val xml : NodeSeq = ... 
xml should matchXML(expected) 

przyczyny:

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)) 

Wszelkie pomysły, co to oznacza?

+0

Jaka jest definicja NodeSeq? –

+0

@ MikaëlMayer Przypuszczam, że 'scala.xml.NodeSeq' – gzm0

Odpowiedz

7

Dlaczego tego nie typecheck:

rodzaju prace sprawdzania w następujący sposób.

xml.should(matchXML(expected)) 
  • Ponieważ metoda should nie jest częścią NodeSeq, kompilator próbuje znaleźć implicit conversion dla xml do ShouldMatcher. Książka „Programowanie w Scala” określa, że ​​takie niejawna konwersja powinna być najbardziej specyficzny:

„Up poprzez Scala 2.7, który był koniec historii Ilekroć stosowany wielokrotne konwersje niejawne, kompilator. odmówił wyboru między nimi ... Scala 2.8 rozluźnia tę regułę.Jeśli jedna z dostępnych konwersji jest ściśle bardziej szczegółowa niż pozostałe, to kompilator wybierze bardziej konkretny. ... jedna niejawna konwersja jest bardziej specyficzne niż inne, jeśli ma zastosowanie jeden z następujących argumentów: Typ argumentu pierwszego z nich to ubty tego drugiego. ..”

  • Ponieważ NodeSeq rozciąga Seq[Node] poniższa funkcja

    convertToSeqShouldWrapper[T](o : scala.GenSeq[T]) : SeqShouldWrapper[T]

    dlatego jest najbardziej specyficzny spośród wszystkich innych.

Program został przepisany jako:

`convertToSeqShouldWrapper(xml).should(matchXML(expected))` 

gdzie convertToSeqShouldWrapper(xml) to SeqShouldWrapper[T] gdzie T = GenSeq[Node].

Metoda should z SeqShouldWrapper akceptuje Matcher[T], która jest funkcją typu T => MatchResult. Dlatego akceptuje on kod Matcher[GenSeq[Node]].

Ponieważ T pojawia się po lewej stronie strzałki, dopasowania nie są covariant w T, ale contravariant.A NodeSeq to GenSeq[Node], więc Matcher[GenSeq[Node]] jest Matcher[NodeSeq], a nie odwrotnie. Wyjaśnia to powyższy błąd, w którym metoda should nie może zaakceptować Matcher[NodeSeq] i wymaga Matcher[GenSeq[Node]].

2 Solutions

  • zastąpić wszystkie wystąpienia NodeSeq do GenSeq[Node] tak że typ pasuje wszędzie.
  • Alternatywnie, owinąć xml explicitely za pomocą funkcji konwersji.

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

+0

Podczas gdy drugie rozwiązanie działa, pierwsze (konwertowanie wszystkiego na 'Seq [Node]') nadal pokazuje ten sam błąd. – HRJ

+0

Udało mi się to rozwiązać, konwertując wszystko na "GenSeq [Node]". Używam 'skalatest 2.0 M5', stąd może różnica. – HRJ

+0

Rzeczywiście, w tej wersji sygnaturą metody convertToSeqShouldWrapper jest "GenSeq [T] => SeqShouldWrapper [T]". Więc zaktualizowałem swoją odpowiedź. –

-1

To wygląda na to, że twoja metoda matchXML nie jest objęta zakresem.

+0

Mam ten sam błąd, nawet jeśli matchXML jest w zakresie. –

Powiązane problemy