Тестирование Scala: замена реализации функции

Используя ScalaTest, я хочу заменить реализацию функции в тестовом примере. Мой вариант использования:

object Module {
  private def currentYear() = DateTime.now().year.get

  def doSomething(): Unit = {
    val year = currentYear()
    // do something with the year
  }
}

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

В динамических языках я часто использовал конструкцию, которая может заменить реализацию функции и вернуть фиксированное значение.

Я хотел бы, чтобы мой тестовый пример изменил реализацию Module.currentYear, чтобы всегда возвращать 2014 год, независимо от фактического года.

Я нашел несколько фиктивных библиотек (Mockito, ScalaMock,...), но все они могли создавать только новые фиктивные объекты. Казалось, ни один из них не может заменить реализацию метода.

Есть ли способ сделать это? Если нет, то как я могу тестировать такой код, не завися от года запуска теста?


person Heinzi    schedule 03.08.2014    source источник


Ответы (2)


Одним из способов было бы просто сделать do_something_with_the_year доступным для вашего тестового примера (например, сделать его защищенным от пакетов). Это также хорошо, потому что разделяет поиск зависимостей и фактическое их использование.

Другой способ — поместить вашу логику в трейт, сделать метод currentYear защищенным и позволить объекту быть экземпляром этого трейта. Таким образом, вы могли бы просто создать пользовательский объект из трейта в тесте, и вам не понадобилась бы какая-либо фиктивная библиотека.

person johanandren    schedule 03.08.2014
comment
оба правильные решения, но мне не нравится дизайн. Пользователям Module не нужно знать, что Module делает что-то с годом. Динамические языки позволяют заглушать функции таким образом. Разве в scala нет способа сделать это? - person Heinzi; 03.08.2014
comment
Это был бы публичный интерфейс, часть объекта, который был бы реализован в трейте, это была бы деталь частной реализации пакета, поэтому пользователям не нужно было бы об этом знать. Если вы действительно хотите имитировать динамические языки, посмотрите ответ samthebests о scalamock. - person johanandren; 05.08.2014

ScalaMock может имитировать одноэлементные объекты, как сказано здесь: http://paulbutcher.com/2011/11/06/scalamock-step-by-step/

Помимо трейтов (интерфейсов) и функций, он также может имитировать:

Классы

Одноэлементные и сопутствующие объекты (статические методы)...

person samthebest    schedule 03.08.2014