2013-05-02 2 views
6

Sto funzionando in un problema durante la scrittura di un matcher personalizzato per NodeSeq:ScalaTest - scrittura personalizzato matchers

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

Questo compila, ma il seguente pezzo di codice:

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

cause:

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

Qualche idea cosa significa?

+0

Qual è la definizione di NodeSeq? –

+0

@ MikaëlMayer Suppongo 'scala.xml.NodeSeq' – gzm0

risposta

7

Perché questo non riesce a TYPECHECK:

Il tipo di opere correttore nel modo seguente.

xml.should(matchXML(expected)) 
  • Poiché il metodo should non è parte di un NodeSeq, il compilatore cerca di trovare una implicit conversion per xml ad un ShouldMatcher. Il libro "Programming in Scala" specifica che tale conversione implicita dovrebbe essere il più specifico:

"Up attraverso la Scala 2.7, che è stata la fine della storia Ogni volta più conversioni implicite applicate, il compilatore. rifiutato di scegliere tra ... Scala 2.8 allenta questa regola Se una delle conversioni disponibili di è strettamente più specifica delle altre, allora il compilatore sceglierà quello più specifico ... una conversione implicita è più speci fi co di un altro se si applica una delle seguenti condizioni: il tipo di argomento del primo è come ubtype di quest'ultimo. .."

  • Poiché NodeSeq estende Seq[Node], la seguente funzione

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

    è pertanto la più specifica tra tutti gli altri.

Il programma viene riscritto come:

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

dove convertToSeqShouldWrapper(xml) è un SeqShouldWrapper[T] dove T = GenSeq[Node].

Il metodo should da SeqShouldWrapper accetta un Matcher[T] che è una funzione di tipo T => MatchResult. Pertanto, accetta uno Matcher[GenSeq[Node]].

Poiché T è visualizzato a sinistra della freccia, i corrispondenti non sono covariant in T, ma controvariante.Un NodeSeq è un GenSeq[Node], quindi un Matcher[GenSeq[Node]] è un Matcher[NodeSeq], non l'opposto. Questo spiega l'errore sopra riportato, in cui il metodo should non può accettare un Matcher[NodeSeq] e richiede un Matcher[GenSeq[Node]].

2 Soluzioni

  • sostituire tutte le istanze di NodeSeq a GenSeq[Node] in modo che il tipo corrispondente in tutto il mondo.
  • In alternativa, avvolgere xml in modo esplicito con la funzione di conversione.

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

+0

Mentre la seconda soluzione funziona, la prima (convertendo tutto in 'Seq [Node]') mostra ancora lo stesso errore. – HRJ

+0

Sono stato in grado di risolvere questo convertendo tutto in 'GenSeq [Node]'. Sto usando 'scalatest 2.0 M5', quindi forse la differenza. – HRJ

+0

Infatti, con questa versione, la firma del metodo convertToSeqShouldWrapper è 'GenSeq [T] => SeqShouldWrapper [T]'. Così ho aggiornato la mia risposta. –

-1

Questo mi sembra che il tuo metodo matchXML non sia incluso.

+0

Ho ottenuto lo stesso errore anche se matchXML è in ambito. –