Сопоставители org.specs2.mock.Mockito не работают должным образом

Вот код, который я пытаюсь запустить:

import org.specs2.mock.Mockito
import org.specs2.mutable.Specification
import org.specs2.specification.Scope
import akka.event.LoggingAdapter

class MySpec extends Specification with Mockito {


  "Something" should {
      "do something" in new Scope {

      val logger = mock[LoggingAdapter]

      val myVar = new MyClassTakingLogger(logger)

      myVar.doSth()

      there was no(logger).error(any[Exception], "my err msg")
      }
  }

}

При запуске этого я получаю следующую ошибку:

[error]    org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
[error]    Invalid use of argument matchers!
[error]    2 matchers expected, 1 recorded:
[error]    -> at         org.specs2.mock.mockito.MockitoMatchers$class.any(MockitoMatchers.scala:47)
[error]
[error]    This exception may occur if matchers are combined with raw values:
[error]        //incorrect:
[error]        someMethod(anyObject(), "raw String");
[error]    When using matchers, all arguments have to be provided by matchers.
[error]    For example:
[error]        //correct:
[error]        someMethod(anyObject(), eq("String by matcher"));

Что имело бы большой смысл, но ни eq("my err msg"), ни equals("my err msg") не работают, так как я получаю сообщение об ошибке. Что мне не хватает?


person eddyP23    schedule 07.09.2015    source источник
comment
eq("my err msg") требуется для этого случая, и я подозреваю, что ошибка, которую вы получаете при его использовании, является другой ошибкой, возможно, связанной с вашим фактическим тестом. Не могли бы вы вставить ошибку, которую вы получаете при использовании eq?   -  person Jeff Bowman    schedule 07.09.2015
comment
Это очень расплывчатая ошибка компиляции: [error] (template: String,arg1: Any)Unit <and> [error] (cause: Throwable,message: String)Unit [error] cannot be applied to (Exception, Boolean) [error] there was no(logger).error(any[Exception], eq("my err msg"))   -  person eddyP23    schedule 08.09.2015


Ответы (2)


Когда вы используете сопоставители для сопоставления параметров, вы должны использовать их для всех параметров. как указывает all arguments have to be provided by matchers.

Более того, если вы используете сопоставитель specs2, он должен быть строго типизирован. equals - это Matcher[Any], но нет преобразования из Matcher[Any] в String, которое принимает method.

Так что вам нужен Matcher[T] или Matcher[String] в вашем случае. Если вы просто хотите проверить равенство, строго типизированный сопоставитель — ===

there was no(logger).error(any[Exception], ===("hey"))
person Eric    schedule 08.09.2015
comment
Как бы вы создали произвольный Matcher[String]? - person eddyP23; 08.09.2015
comment
Как будто вы могли бы легко хотеть сопоставлять, например, содержит или содержится в или что-то подобное - person eddyP23; 08.09.2015
comment
Вы знаете, как я мог написать сопоставитель, который также принимает правый параметр? В частности, мне интересно написать сопоставитель, который проверяет, содержит ли левая строка строку справа: "some string" should containString "me st" @Eric - person eddyP23; 02.06.2016
comment
Да, используйте параметр: def containString(expected: String): Matcher[String] = { actual: String => (actual.contains(expected), "wrong") }. - person Eric; 02.06.2016
comment
Вышеупомянутое не сработало, но с небольшой модификацией сработало следующее: def containString(right: String): Matcher[String] = new Matcher[String] { def apply(left: String) = MatchResult(left.contains(right), s"'$left' does not contain '$right'", s"'$left' contains '$right'") } - person eddyP23; 02.06.2016
comment
Версия, которую я вам дал, должна работать, если вы импортируете org.specs2.matcher.MatcherImplicits._, когда вы не соответствуете спецификации. - person Eric; 02.06.2016

Я хотел бы добавить, что вам следует с осторожностью относиться к аргументам по умолчанию, т. е. если вы используете сопоставители при заглушке методов, обязательно передайте сопоставители аргументов для всех аргументов, потому что аргументы по умолчанию будут почти наверняка имеют постоянные значения, что приводит к появлению этой же ошибки.

Например. заглушить метод

def myMethod(arg1: String, arg2: String arg3: String = "default"): String

вы не можете просто сделать

def myMethod(anyString, anyString) returns "some value"

но вам также нужно передать сопоставитель аргументов для значения по умолчанию, например:

def myMethod(anyString, anyString, anyString) returns "some value"

Потерял полчаса, пока разбирался :)

person Zoltán    schedule 01.12.2015
comment
Это следует упомянуть в выбранном ответе, это просто сэкономило мне много времени и разочарований. - person K. C.; 29.10.2016