我需要一些关于如何使用 ScalaMock 模拟类内高阶函数的帮助
import org.scalamock.scalatest.MockFactory
import org.scalatest.{FlatSpec, Matchers}
class TestSpec extends FlatSpec with MockFactory with Matchers {
class Foo {
def foo(f: () ⇒ String) = "this is foo"
}
val fooMock = mock[Foo]
"Failing test" should "pass but doesn't" in {
(fooMock
.foo(_: () ⇒ String))
.expects({ () ⇒
"bar"
})
.returns("this is the test")
// will fail here
val result = fooMock.foo({ () ⇒
"bar"
})
assert(true)
}
"Passing test" should "that passes but I can't do it this way" in {
val f = { () ⇒
"bar"
}
(fooMock.foo(_: () ⇒ String)).expects(f).returns("this is the test")
val result = fooMock.foo(f)
result shouldBe "this is the test"
}
}
正如您在上面的代码中看到的那样,当您传入具有高阶函数的值时,被模拟的函数工作正常,但如果在每个位置键入它,则不会。在我的用例中,我不能像在第二个测试中那样做
以下是有关用例的更多信息,但并非完全需要回答此问题
这是一个简化的示例,但我需要一种方法来使前者工作。原因是(我会尽力解释这一点(我有一个正在测试的 A 类。A 内部是一个传递模拟类 B 的函数,基本上 foo 函数(如下所示(位于这个模拟的 B 内部,我不能像下面的第二个示例中那样只传入 f。如果这没有任何意义,我可以尝试完全复制它。
TL;DR 我需要第一个测试才能工作,哈哈
知道为什么会发生这种情况吗?
如果您对我为什么需要这样做感到好奇,这里有一个更确切的示例,说明我如何使用它:
import org.scalamock.scalatest.MockFactory
import org.scalatest.{FlatSpec, Matchers}
class TestSpec extends FlatSpec with MockFactory with Matchers {
class Foo {
def foo(f: () ⇒ String) = s"you sent in: ${f()}"
}
object Bar {
def bar(foo: Foo): String = {
val f = { () ⇒ "bar" }
foo.foo(f)
}
}
val fooMock = mock[Foo]
"Failing test" should "pass but doesn't" in {
(fooMock.foo(_: () ⇒ String))
.expects({ () ⇒
"bar"
})
.returns("this is the test")
// will fail here
val result = Bar.bar(fooMock)
assert(true)
}
}
这不起作用的原因归结为 Scala 本身。 例如,请参阅此 scala repl:
scala> val f = { () ⇒ "bar" }
f: () => String = $$Lambda$1031/294651011@14a049f9
scala> val g = { () ⇒ "bar" }
g: () => String = $$Lambda$1040/1907228381@9301672
scala> g == f
res0: Boolean = false
因此,在没有帮助的情况下,ScalaMock也无法比较函数的相等性。 我的建议是,如果您只对函数的结果感兴趣,请使用谓词匹配,如以下文档中所述:http://scalamock.org/user-guide/matching/
在谓词中,您可以计算捕获的参数并检查返回值是否确实bar
。或者,如果你的函数更复杂,也许你甚至可以做一个mock[() => String]
并在匹配器中比较引用相等性?