Как создать заглушку ScalaMock, которая не вызывает конструктор базового объекта?

Рассмотрим следующий пример класса Scala и модульного теста:

class BrokenClass(s: String) {
  private val len = s.length
  def length(): Int = len
}

class BrokenTest extends FlatSpec with Matchers with MockFactory {

  "A BrokenClass" should "stub correctly" in {
    val stubThing = stub[BrokenClass]
    (stubThing.length _) when () returns (10)
    stubThing.length should equal (10)
  }

}

В более старых версиях ScalaMock этот код будет работать. В Scala 2.12 и ScalaMock 3.6 я получаю исключение NullPointerException, потому что, хотя я создаю заглушку, она по-прежнему вызывает строку «s.length» конструктора BrokenClass. Итак, он пытается разыменовать "s", который равен нулю, потому что я ничего ему не передал, потому что все, что мне нужно, это заглушка, которая возвращает определенное значение при вызове определенного метода.

Есть ли способ создать заглушку, не пытаясь вызвать конструктор объекта? Почему это работало в старых версиях?


person Huitzilopochtli    schedule 12.07.2018    source источник


Ответы (1)


ScalaMock генерирует подклассы, используя определение макроса. Этот макрос расширяется/оценивается во время запуска компилятора.

Поскольку макеты являются подклассами, будут вызываться конструкторы суперклассов — без исключений. Возможно, вы сможете обойти это, используя некоторое колдовство cglib, но это не то, с чем я знаком.

Таким образом, это могло быть возможно в более старых версиях ScalaMock, но эта функция не вернется в ближайшее время с текущей реализацией.

другой вариант - фактически создать подкласс этой вещи и издеваться над подклассом

class NotSoBrokenClass extends BrokenClass("")
...
val nsb = mock[NotSoBrokenClass]
...

В некоторых случаях это работает, но если конструктор зависит от нефинальных вызовов методов, вы также увидите забавное поведение (например, NPE).

person Philipp    schedule 13.07.2018
comment
Это приятно знать, спасибо. Я не знал, что ScalaMock только что сгенерировал подклассы. Я полагаю, это научит меня обрабатывать входные данные нулевого конструктора. - person Huitzilopochtli; 19.07.2018