Scalamock:使用参数模拟调用按名称函数

问题描述

在以下代码段中,我需要确保调用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]()

解决方法

现在,我了解自己在犯的错误;我试图将Foo#foo的curry-by-name传递为放置在其中的函数,在上面的示例中为BinaryConverter#intToStr(x: Int): String

相反,应将参数强制转换为() => String,然后再调用它,以便可以执行内部代码。

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