Scala mock: вызов экземпляра шпионского макета, когда другой экземпляр класса инициируется внутри объекта

У меня есть класс SomeClass в объекте scala и SomeClass. теперь мне нужно смоделировать OtherClass, который создается в объекте SomeClass

    class SomeClass {
            import SomeClass._
            def doSomething(param1:Map[String,String],param2:Int) :String{ 
            val returnForSomething= instanse.otherClassFuntion(param2)
        .....
         }

            def doSomethingElse(param:Int) :Map[String,String]{ 
           val returnForSometingElse= instanse.otherClassFuntion(param)
        ....
        }

    object SomeClass{
        lazy val instance =new OtherClass
     }

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

 val instance = spy(new OtherClass)

но как передать этот экземпляр, когда объект вызывает новый экземпляр в объекте SomeClass


person Kalpish Singhal    schedule 21.05.2020    source источник


Ответы (1)


Вы не можете имитировать значения в objects. У них нет конструкторов, которые позволили бы вам внедрять зависимости. Они служат той же цели, что и классы со статическими методами.

Если вам действительно нужна эта функциональность, вам придется создать какой-то сеттер, позволяющий переопределить instance:

object SomeClass {
  private var _instance = new OtherClass

  def instance = _instance

  // put your package name in []
  private[thispackage] def instance_=(newInstance: OtherClass) = _instance = OtherClass
  // to make it accessible only within thispackage and its subpackages
}

Однако, учитывая, что:

  • object являются глобальными (точно так же, как методы static в Java)
  • глобальное изменяемое состояние почти всегда плохо
  • и поэтому objects (и static методы) должны быть без состояния, если вы хотите написать тестируемый код

что-то не так с этим вариантом использования. instance не должно требовать насмешек, фальсификаций или шпионажа. Если это так, то его НЕ следует использовать как глобальный изнутри SomeClass, а скорее значение по умолчанию, переданное через конструктор, которое можно заменить:

class SomeClass(instance: OtherClass = SomeClass.instance) {
  ...
}

или что-то вроде того.

person Mateusz Kubuszok    schedule 21.05.2020