2013-09-05 1 views
8

Я тестирую модульное тестирование с помощью платформы Play в scala. Я написал класс, который проверяет, правильно ли конфигурация (у меня есть обработка ошибки немного больше, но я на самом деле использовать этот код для моего теста сейчас):Тесты проверки Mockito scala не работают (play framework)

class TaskQueueConfig(conf: Configuration) { 
    val schedulingEnabled = conf.getBoolean("schedulingEnabled").get 
    val processingEnabled = conf.getBoolean("processingEnabled").get 
    val queueName = conf.getString("queue").get 
} 

Я проверяю это с помощью играть 2.1. 1 по испытательной установке по умолчанию:

class ConfigTestSpec extends Specification with Mockito with CalledMatchers { 
    "TaskQueueConfig" should { 
    "verify calls" in { 
     val tqConf = mock[Configuration] 
     tqConf.getString("queue") returns Some("queueName") 
     tqConf.getBoolean("schedulingEnabled") returns Some(true) 
     tqConf.getBoolean("processingEnabled") returns Some(true) 
     Logger.error("setup done") 

     val config = new TaskQueueConfig(tqConf) 

     there was one(tqConf).getString("queue") 
     there were two(tqConf).getBoolean(any[String]) 
     there were one(tqConf).getBoolean("schedulingEnabled") 
     there were one(tqConf).getBoolean("processingEnabled") 
    } 
    } 
} 

Я получаю следующее сообщение об ошибке:

[error] x verify calls 
[error] The mock was not called as expected: 
[error] configuration.getString$default$2(); 
[error] Wanted 1 time: 
[error] -> at config.ConfigTestSpec$$anonfun$2$$anonfun$apply$4$$anonfun$apply$12.apply(ConfigTestSpec.scala:61) 
[error] But was 2 times. Undesired invocation: 
[error] -> at config.TaskQueueConfig.<init>(TaskQueueConfig.scala:10) (ConfigTestSpec.scala:61) 

Это очень странно, потому что код очень изолирован и есть явно только 1 конф .getString в TaskQueueConfig. Строка 10 - это строка с методом getString. Строка 61 - это строка с «была одна (tQConf) .getString»

Как я могу исправить эту проблему?

(разница между есть и был).

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

метод ОБНОВЛЕНИЕ 1 GetString имеет два параметра, второй параметр имеет значение по умолчанию None (это тип Опция [Установить [String]]). Когда я явно добавляю None к настройке и проверке, он все равно не работает. Но когда я добавляю null, я заставляю его работать.

val tqConf = mock[Configuration] 

    tqConf.getString("queue", null) returns Some("queueName") 
    tqConf.getBoolean("schedulingEnabled") returns Some(true) 
    tqConf.getBoolean("processingEnabled") returns Some(true) 

    val c = new TaskQueueConfig(tqConf) 

    there was one(tqConf).getString("queue", null) 
    there was one(tqConf).getString(any[String], any[Option[Set[String]]]) 
    there were two(tqConf).getBoolean(any[String]) 
    there was one(tqConf).getBoolean("schedulingEnabled") 
    there was one(tqConf).getBoolean("processingEnabled") 

    c.processingEnabled must beTrue 
    c.schedulingEnabled must beTrue 
    c.queueName must be("queueName") 

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

+0

Почему вы проверка, что было назван на ложно конфиге против просто проверок конечного состояния создаваемого объекта? Если вы правильно закоулили, вам следует просто проверить, соответствуют ли значения свойств «TaskQueueConfig» заданные вами значения. Я знаю, что это не отвечает на ваш вопрос, но это наверняка устранит эту проблему для вас ... – cmbaxter

+0

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

+0

Мои две первоначальные мысли заключались в том, что либо подсчет был подсчитан (поэтому он сделал два вызова), либо у вас была проблема с определением области охвата, и еще одна последовательность тестов также подсчитывалась, таким образом, дополнительный вызов 'getString'.Я сам испытал первую теорию, и мне не кажется, что mockito случайно включает в себя окунирование в счете. Для проблемы определения области обзора, если ваш реальный код такой, какой он есть, и макет не создается глобально, это тоже не должно быть проблемой. – cmbaxter

ответ

4

Вы должны использовать null в два-аргументе getString() вызова, потому что Mockito требует либо использовать использование matchers для всех аргументов или вообще ни.

Так что смешение "queue" (буква) с any[Option[Set[String]]] (совпадение) не будет работать. Иногда Mockito может решить, что вы сделали это, и это дает вам ошибку, но кажется, что вам не повезло здесь ...

Попробуйте использовать matchers во всех позициях, как это:

tqConf.getString(org.mockito.Matchers.eq("queue"), any[Option[Set[String]]]) returns Some("queueName") 

и проверки:

there was one(tqConf).getString(eq("queue"), any[Option[Set[String]]]) 
+0

Спасибо! У меня есть еще один связанный с этим вопрос, можете ли вы объяснить, почему tqConf.getString («queue», None) Return Some («queueName») не работает? Когда я это делаю, я получаю NPE в коде, который вызывает getString («queue»). Get None - это значение по умолчанию для второго необязательного параметра getString ... – Jaap

+1

Я думаю, что вы действительно на самом деле поразили действительно интересные для аргументов Mockito по сравнению с аргументами по умолчанию Scala. Я тестировал комбинации, и единственные, которые работают: 'tqConf.getString (« queue ») возвращает Some (« queueName »)» (т.е. напрямую использует ровно один литерал, игнорируя полностью аргумент по умолчанию) и 'tqConf .getString (org.mockito.Matchers.eq («queue»), любой [Option [Set [String]]]) возвращает Some («queueName») »(т.е. используя совпадения для аргументов _both_, как и рекомендация Mockito). Я бы предпочел вторую форму для объяснения, но это интересно ... – millhouse