使用按名称传递的参数模拟函数
Mocking a function with pass-by-name arguments
我的实际用例是涉及 finagle 的单元测试代码 FuturePool
:我想确定 FuturePool.apply
确实被调用了,以便任务在池的正确实例中执行.
我正在 运行 遇到的问题似乎更笼统,所以我将用一个与 finagle 或 futures 无关的抽象示例来说明它。
假设,我有这两个类:
class Foo {
def apply(f: => String) = f
}
class Bar(val foo: Foo) {
def doit(f: => String) = foo(f)
}
Bar
有一个 Foo
的实例,它知道如何 运行 函数,我想测试它是否实际使用它来执行:
describe("Bar") {
it("should use the right foo") {
val foo = mock[Foo]
when(foo.apply(any)).thenAnswer( new Answer[String] {
def answer(invocation: InvocationOnMock): String =
invocation.getArgumentAt(0, classOf[Function0[String]]).apply()
})
new Bar(foo).doit("foo") should equal("foo")
}
}
这不起作用:.doit
return null,显然,因为 mockito 没有意识到它被模拟了。在这种情况下,any
似乎与 Function0
不匹配(将其替换为 any[Function0[String]]
也无济于事。
我也试过另一种方式:
it("should Foo!") {
val foo = Mockito.spy(new Foo)
new Bar(foo).doit("foo") should equal("foo")
verify(foo).apply(any)
}
这也不起作用,有点证实了我对 any
在这种情况下不起作用的怀疑:
Argument(s) are different! Wanted:
foo.apply(
($anonfun$apply$mcV$sp) <function0>
);
Actual invocation has different arguments:
foo.apply(
($anonfun$apply$mcV$sp) <function0>
);
关于解决这个问题的好方法有什么想法吗?
这个签名:
def apply(f: => String)
被称为 "call by name",它传递一个表达式而不是计算的表达式。这是 Scala 特有的,Mockito 没有很好地支持它。
对此有许多解决方法:
Is there a way to match on a call-by-name argument of a Mockito mock object in Specs?
How to mock a method with functional arguments in Scala?
How do you mock scala call-by name in Mockito
one by Eric看起来最简单,也是你想要的。
我的实际用例是涉及 finagle 的单元测试代码 FuturePool
:我想确定 FuturePool.apply
确实被调用了,以便任务在池的正确实例中执行.
我正在 运行 遇到的问题似乎更笼统,所以我将用一个与 finagle 或 futures 无关的抽象示例来说明它。
假设,我有这两个类:
class Foo {
def apply(f: => String) = f
}
class Bar(val foo: Foo) {
def doit(f: => String) = foo(f)
}
Bar
有一个 Foo
的实例,它知道如何 运行 函数,我想测试它是否实际使用它来执行:
describe("Bar") {
it("should use the right foo") {
val foo = mock[Foo]
when(foo.apply(any)).thenAnswer( new Answer[String] {
def answer(invocation: InvocationOnMock): String =
invocation.getArgumentAt(0, classOf[Function0[String]]).apply()
})
new Bar(foo).doit("foo") should equal("foo")
}
}
这不起作用:.doit
return null,显然,因为 mockito 没有意识到它被模拟了。在这种情况下,any
似乎与 Function0
不匹配(将其替换为 any[Function0[String]]
也无济于事。
我也试过另一种方式:
it("should Foo!") {
val foo = Mockito.spy(new Foo)
new Bar(foo).doit("foo") should equal("foo")
verify(foo).apply(any)
}
这也不起作用,有点证实了我对 any
在这种情况下不起作用的怀疑:
Argument(s) are different! Wanted:
foo.apply(
($anonfun$apply$mcV$sp) <function0>
);
Actual invocation has different arguments:
foo.apply(
($anonfun$apply$mcV$sp) <function0>
);
关于解决这个问题的好方法有什么想法吗?
这个签名:
def apply(f: => String)
被称为 "call by name",它传递一个表达式而不是计算的表达式。这是 Scala 特有的,Mockito 没有很好地支持它。
对此有许多解决方法:
Is there a way to match on a call-by-name argument of a Mockito mock object in Specs?
How to mock a method with functional arguments in Scala?
How do you mock scala call-by name in Mockito
one by Eric看起来最简单,也是你想要的。