【发布时间】:2014-09-26 17:29:46
【问题描述】:
假设我有这个类:
class Defaults {
def doSomething(regular: String, default: Option[String] = None) = {
println(s"Doing something: $regular, $default")
}
}
我想检查其他一些类在 Defaults 实例上调用 doSomething() 方法而不传递第二个参数:
defaults.doSomething("abcd") // second argument is None implicitly
但是,模拟 Defaults 类无法正常工作。因为方法参数的默认值编译为同一类中的隐藏方法,mock[Defaults] 返回一个对象,其中这些隐藏方法返回null 而不是None,因此此测试失败:
class Test extends FreeSpec with ShouldMatchers with MockitoSugar {
"Defaults" - {
"should be called with default argument" in {
val d = mock[Defaults]
d.doSomething("abcd")
verify(d).doSomething("abcd", None)
}
}
}
错误:
Argument(s) are different! Wanted:
defaults.doSomething("abcd", None);
-> at defaults.Test$$anonfun$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(Test.scala:14)
Actual invocation has different arguments:
defaults.doSomething("abcd", null);
-> at defaults.Test$$anonfun$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(Test.scala:12)
原因很清楚,但是否有合理的解决方法?我看到的唯一一个是使用spy() 而不是mock(),但是我的模拟类包含很多方法,在这种情况下我必须显式模拟,我不想要它。
【问题讨论】:
-
很遗憾,如果您使用参数匹配器,则所有参数都必须由匹配器提供 docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#3
-
@JhonnyEverson,我从未说过我在使用匹配器。您可以从我的示例中看到没有使用单个匹配器。
-
啊,对,对不起。也许您可以使用一些隐式参数而不是默认参数,但我不确定它是否会起作用。只是一个想法。
-
我不确定 Mockito 能做到这一点。在您的情况下,
d只是一个标准 Java 代理,它在内部调用Defaults的真实实例。由于 Java 没有 Some/None 范式的概念,因此在动态绑定参数时它将使用 null - 对于 Java,您的 doSomething() 方法是一个普通的 2 参数方法,因此反射调用需要用一些东西填充 arg 列表,在你的情况下是null。顺便说一句,你试过用原生 ScalaMock 解决这个问题吗?
标签: scala mockito default-arguments