Scala Mock частичная заглушка

Я хотел бы заглушить один из методов класса scala с зависимостями. Есть ли способ добиться этого с помощью ScalaMock?

Вот упрощенный пример того, что у меня есть:

class TeamService(val dep1: D1) {

  def method1(param: Int) = param * dep1.magicNumber()

  def method2(param: Int) = {
    method1(param) * 2
  }
}

В этом примере я хотел бы издеваться над method1(). Мой тест будет выглядеть так:

val teamService = ??? // creates a stub
(teamService.method1 _).when(33).returns(22)
teamService.method2(33).should be(44)

Есть ли способ добиться этого?


person Danix    schedule 26.01.2016    source источник
comment
Я думаю, что если вы издеваетесь над каким-то классом, вы не хотите зависеть от его реализации, но теперь вы, похоже, пытаетесь зависеть от реализации method1 и D1. Возможно, информации недостаточно, но вам, возможно, следует издеваться над всеми методами, которые вам нужно использовать.   -  person Łukasz    schedule 26.01.2016
comment
похоже, scala mock не поддерживает эту функцию :(   -  person Danix    schedule 18.05.2016
comment
Я полагаю, что здесь есть проблема с этой функцией: github.com/paulbutcher/ScalaMock/issues/ 141   -  person Quentin    schedule 07.11.2016


Ответы (3)


Вы должны издеваться над dep1: D1, чтобы все работало хорошо. Нехорошо издеваться над «половиной» или только над некоторыми методами.

Насмешка над dep1: D1 — это правильный способ проверить это.

val mockD1 = mock[D1]
val teamService = new TeamService(mockD1)
(mockD1.magicNumber _).returns(22)
teamService.method2(33).should be(44)
person Henrique dos Santos Goulart    schedule 19.09.2017

Как было предложено в других вопросах, здесь и здесь мы можем объединить stub с final. Из часто задаваемых вопросов по ScalaMock:

Могу ли я издеваться над окончательными/приватными методами или классами?

Это не поддерживается, так как макеты, сгенерированные с помощью макросов, реализуются как подклассы типа для имитации. Таким образом, частные и окончательные методы не могут быть переопределены.

Таким образом, вы можете либо объявить method2 в исходном коде как окончательный, а затем протестировать:

it should "test" in {
  val teamService = stub[TeamService]
  (teamService.method1 _).when(33).returns(22)
  teamService.method2(33) shouldBe 44
}

Или создайте новый класс переопределения, который объявляет ваш метод окончательным:

it should "test" in {
  class PartFinalTeamService(dep: D1) extends TeamService(dep) {
    override final def method2(param: Int): Int = super.method2(param)
  }

  val teamService = stub[PartFinalTeamService]
  (teamService.method1 _).when(33).returns(22)
  teamService.method2(33) shouldBe 44
}
person Tomer Shetah    schedule 05.11.2020

Вы можете переопределить method1() при создании объекта TeamService и заставить его возвращать любое значение, которое вы хотите.

val service = new TeamService(2) {
  override def method1(param: Int): Int = theValueYouWant
}

И используйте объект service для проверки вашего method2().

person Manoj Kumar    schedule 16.07.2021