unit-testing - 你如何嘲笑平等?
问题描述
假设我有一个界面
interface IFoo{
val foo:String
}
我想创建与它们的foo
字符串匹配的 IFF 相等的类。
简单的例子:
class A(override val foo:String):IFoo{
val somethingIrrelevant = "bar"
override fun equals(other: Any?): Boolean {
return if(other is IFoo) foo == other.foo else false
}
override fun hashCode(): Int {
return Objects.hash(foo)
}
}
看起来相对简单,但是这个测试用例:
@Test
fun mockingEquality(){
//given
val a = A("alpha")
val b = A("alpha")
assertThat(a,`is`(b)) //succeeds
//when
val c = mock(A::class.java)
whenever(c.foo).thenReturn("alpha")
//then
assertThat(c, `is`(a)) //fails
}
失败了
Expected: is <A@589b17d>
but: was <Mock for A, hashCode: 263885523>
这是为什么?以及如何正确模拟A
课程以使该测试成功?
解决方案
这里的问题是,当您创建模拟时,该对象没有任何行为,除非您明确模拟它。这包括你的equals
和hashCode
方法。
在您的示例中,一个“修复”是模拟equals
andhashCode
方法,但显然这不会为您的测试增加任何价值。简单地说,您可以反转您的断言 ( assertThat(a, is(c))
),这恰好可以工作,因为最终结果将是a.equals(c)
, 并且a
是类的真实实例A
而不是模拟,并且具有.foo
模拟属性。
我怀疑您的示例过于简化,但在那些给定的情况下,您应该更喜欢只创建一个真实实例而不是模拟(例如val c = A("alpha")
,而不是mock(A::class.java)
)。
这里的一些其他方法可能是:
如果您可以获得该类的真实实例,另一种方法是使用间谍。例如:
val c = spy(A("other value"))
doReturn("mock value").whenever(c).foo
但是您可以在文档中看到,这些部分模拟类的方法不是推荐的方法。
推荐阅读
- c# - 在 c# 中使用 lambda 或 linkq 查找项目索引
- c# - 为什么对原始值使用表达式体属性?
- python - 如何从python中具有各种列表的字符串列表中提取信息
- asp.net-core - asp.net核心中信号器上的javascript xmlhttp错误
- python - 烧瓶上传 + 文件夹创建 + 前端展示
- matrix - Sympy:Matrix 的自定义子类不起作用
- upload - 在 Arduino IDE 中通过空中 (OTA) 上传 ESP32 脚本时出现 Java 错误
- c++ - 将 cin 与数组一起使用
- vb.net - 获取 Barcode 128 编码文本。我想使用条形码字体来显示它,而不是生成图像
- python - 从 C++ PyBind11 中的另一个 Python 文件导入 Python 文件(模块)