Java 无equals实现的正确单元测试属性持有者

Java 无equals实现的正确单元测试属性持有者,java,unit-testing,tdd,mockito,hamcrest,Java,Unit Testing,Tdd,Mockito,Hamcrest,我正在和一位同事讨论我遇到的一个具体情况, 如果有人能提出一些观点或理论基础,那就太好了 假设我们有A类型的模型对象,它们是java bean、属性持有者, 还有像getPrice、getQuantity、getName这样的方法 我们还假设由于某种遗留原因,equals方法返回true, 在两个不同的对象上,即使它们具有不同的属性值 我将提供一些代码来举例说明这个问题。 (显然不是相同的代码,采用快捷方式) 我们想对HandlerA进行单元测试 因此,我们可能希望编写一个如下的测试: publ

我正在和一位同事讨论我遇到的一个具体情况, 如果有人能提出一些观点或理论基础,那就太好了

假设我们有A类型的模型对象,它们是java bean、属性持有者, 还有像getPrice、getQuantity、getName这样的方法

我们还假设由于某种遗留原因,equals方法返回true, 在两个不同的对象上,即使它们具有不同的属性值

我将提供一些代码来举例说明这个问题。 (显然不是相同的代码,采用快捷方式)

我们想对HandlerA进行单元测试

因此,我们可能希望编写一个如下的测试:

public class TestMain {

    @Test
    public void givenA_fHappens() {

        Manager manager = mock(Manager.class);
        HandlerA handler = new HandlerA(manager);

        A givenA = new A(7, 9);

        handler.handle(givenA);
        verify(manager).f(givenA, "abc");
    }
}
现在的问题是,由于equals返回true,因此对于具有不同属性的不同对象,在代码中进行此修改:

    @Override
    public void handle(A a) {
--        m.f(a, "abc");
++        m.f(new A(1, 1), "abc");
    }
单元测试将不包括

我建议我们使用一个匹配器来验证(或者在有参数捕获器的情况下使用断言) 事实上已经有一个叫做, 但是我遇到了批评,我们不想断言它们具有相同的值,只是调用了代码


你觉得怎么样?你对此有何看法?

答案实际上取决于你的测试目标。基于此,答案会有所不同

  • 您是否正在测试传递的实例是否与
    equals
    方法报告的相同?如果是这样,那么
    verify(manager).f(givenA,“abc”)
    就足够了(前提是您相信已经为给定类实现了对象相等)。在大多数情况下,这是可取的,因为它在语义上更有意义,我们不想担心诸如对象引用相等之类的低级细节。在上面的示例中,理想情况下,
    equals
    方法应该是固定的:)

  • 您是否正在测试是否将相同的对象引用传递给该方法?在某些情况下,我们可能希望显式检查所传递的对象是否确实是内部使用的相同引用,而不是由外观相同的对象替代。这是相当罕见的,但是如果有这样的需要,请使用
    ArgumentCaptor
    并断言发送值和捕获值之间的引用相等

  • 说到这里,我们不想断言它们具有相同的值,只是调用了代码


    就我个人而言,我不认为断言调用了该方法就足够了。如果传递的值不同(如您提到的值),该怎么办。这将使测试不完整,并使代码脆弱。这样的测试只会使覆盖率报告看起来是绿色的,但缺乏完整的功能覆盖。

    谢谢您的回答。对象和值不应更改。这只是一个调度逻辑,正确的代码。在我看来,我们应该验证对象仍然具有相同的值。对此有更多的看法会有所帮助
        @Override
        public void handle(A a) {
    --        m.f(a, "abc");
    ++        m.f(new A(1, 1), "abc");
        }