2013-05-02 6 views
6

Я бегу в проблемы при написании пользовательских Искателя для NodeSeq:ScalaTest - написание пользовательских 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") 
} 

Это компилирует, но следующий фрагмент кода:

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? –

+0

@ MikaëlMayer Я бы предположил, что 'scala.xml.NodeSeq' – gzm0

ответ

7

Почему это не в typecheck:

проверки типов работ следующим образом.

xml.should(matchXML(expected)) 
  • Поскольку метод should не является частью NodeSeq, компилятор пытается найти implicit conversion для xml к ShouldMatcher. Книга «Программирование в Scala» указывает, что такое неявное преобразование должно быть самым конкретным:

«Вплоть до Scala 2.7, что был конец истории Всякий раз, когда несколько неявные преобразования применяется, компилятор. отказался выбрать между ними ... Scala 2.8 освобождает это правило.Если одна из доступных конверсий строго больше, чем другие, то компилятор выберет более конкретный вариант ... одно неявное преобразование более конкретным, чем другое, если применяется одно из следующих утверждений: тип аргумента ubtype последнего. ..»

  • Поскольку NodeSeq расширяет Seq[Node], следующую функцию поэтому

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

    является наиболее специфическим среди всех остальных.

Программа переписана as:

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

, где convertToSeqShouldWrapper(xml) является SeqShouldWrapper[T], где T = GenSeq[Node].

Метод should от SeqShouldWrapper принимает 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))

+0

Пока второе решение работает, первое (преобразование всего в 'Seq [Node]') по-прежнему показывает ту же ошибку. – HRJ

+0

Я смог решить это, преобразовывая все в «GenSeq [Node]». Я использую 'scalatest 2.0 M5', отсюда, возможно, разница. – HRJ

+0

Действительно, с этой версией сигнатурой метода convertToSeqShouldWrapper является «GenSeq [T] => SeqShouldWrapper [T]». Поэтому я обновил свой ответ. –

-1

Это выглядит так, как ваш метод matchXML не имеет значения.

+0

Я получил ту же ошибку, даже если matchXML находится в области видимости. –