Scalamock: имитирующий вызов функции по имени с аргументами

#unit-testing #mocking #higher-order-functions #scalamock #callbyname

#модульное тестирование #издевательство #функции более высокого порядка #scalamock #callbyname

Вопрос:

В следующем фрагменте кода мне нужно убедиться, что BinaryConverter#intToStr это вызвано.

 import org.scalamock.scalatest.MockFactory
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class Foo {
  def foo(x: Int)(b: => String): String = b
}
class BinaryConverter {
  def intToStr(x: Int): String = x.toBinaryString
}
class Converter(fooBar: Foo, converter: BinaryConverter) {
  def convert2Bin(x: Int): String = fooBar.foo(x)(converter.intToStr(x))
}
class FooTest extends AnyFlatSpec with Matchers with MockFactory {
  val mockFoo: Foo = mock[Foo]
  val mockBinConverter: BinaryConverter = mock[BinaryConverter]
  val converter = new Converter(mockFoo, mockBinConverter)

  behavior of "Foo"

  it should "mock foo doesn't work" in {
    (mockBinConverter.intToStr _).expects(2).returns("Mock 10")
    (mockFoo.foo(_: Int)(_: String)).expects(2, *).onCall(_.productElement(1).asInstanceOf[Int => String](2))

    converter.convert2Bin(2) shouldBe "Mock 10"
  }
}
  

Я пытался использовать продукт OnCall, но получаю Converter$$Lambda$132/182531396 cannot be cast to scala.Function1 . Хотя, тот же код работает при приведении функции без параметров к Function0, .asInstanceOf[() => String]()

Ответ №1:

Теперь я понимаю ошибку, которую я совершил; Я пытался привести аргумент curried call-by-name Foo#foo для функции, которая была помещена в нее, в приведенном выше примере это BinaryConverter#intToStr(x: Int): String .

Вместо этого параметр должен быть приведен к () => String , а затем вызван, чтобы можно было выполнить код внутри.

(mockFoo.foo(_: Int)(_: String)).expects(2, *).onCall(_.productElement(1).asInstanceOf[() => String]())