unit-testing - 您如何 mock 平等?

标签 unit-testing junit kotlin mockito hamcrest

假设我有一个界面

interface IFoo{
    val foo:String
}

我想创建等于IFF的foo字符串匹配的类。

简单的例子:
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类才能使测试成功?

最佳答案

这里的问题是,当您创建模拟对象时,该对象没有任何行为,除非您明确对其进行模拟。这包括您的equalshashCode方法。

对于您的示例,一个“解决方案”是模拟equalshashCode方法,但是显然,这不会给您的测试增加任何值(value)。琐碎地,您可以反转恰好起作用的断言(assertThat(a, is(c))),因为最终结果将是a.equals(c),并且aA类的真实实例,而不是模拟类,并且具有.foo属性 mock 。

我怀疑您的示例过于简化了,但是在这些给定的情况下,您应该更喜欢创建一个真实的实例而不是模拟(例如val c = A("alpha")而不是mock(A::class.java))。

这里的一些其他方法可能是:

如果您可以获得类的真实实例,则另一种方法是使用 spy 。例如:

val c = spy(A("other value"))
doReturn("mock value").whenever(c).foo 

但是您可以在documentation中看到,不建议使用这些部分模拟类的方法。

关于unit-testing - 您如何 mock 平等?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54542172/

相关文章:

unit-testing - 如何在用 Kotlin 编写的 JUnit 5 测试类中注入(inject) Spring bean?

java - fragment 中的 OnClickListener 不再起作用

unit-testing - 涉及多个类的单元测试逻辑

unit-testing - 当被测类型覆盖 ToString 时,无法运行 TestCaseSource 测试

javascript - 如何在angularjs中测试指令加载与否

java - 如何在 Java 中模拟新对象的创建

java - 如何在没有powermock的情况下模拟静态方法

c++ - CppUnit 期望带有 Assert Throw 的异常编译时带有警告 C4127

java - Xcode 8 Jenkins JUnit 错误 : test report no report files found

从文件中读取字符串时,Kotlin 字符串替换不起作用