什么是JUnit的assertEquals()方法的替代方法,以便在测试报告中看到哪些对象字段在比较时有所不同?

时间:2016-07-28 10:55:47

标签: java junit

我在JUnit上用Java编写了很多自动化测试,我经常使用assertEquals(java.lang.String message, java.lang.Object expected, java.lang.Object actual)。 如果比较基元类型,那么在断言失败的情况下,在测试报告中可以清楚地看到值是不同的,例如,在2个整数比较的情况下。但是当你比较两个复杂的对象时,测试的输出可能会非常混乱。即使您已正确覆盖toString()方法,该方法将列出具有所有值的所有字段,但输出将很长。想象一下上课:

public class Invoice {

    private LocalDate invoiceDate;
    private String invoiceNumber;
    private InvoiceType invoiceType;
    private InvoiceStatus invoiceStatus;
    private String mediaPlanner;
    private String yourReference;
    private String responsiblePerson;
    private Brand advertiser;
    private MediaAgency mediaAgency;
    private Set<InvoiceRow> invoiceRows;
    .....

InvoiceRow也是一个非常复杂的对象,有很多自己的字段。因此,如果我将这些所有字段都放入toString()实现并且断言失败,那么JUnit将输出相当长的消息,这将不容易通过眼睛阅读,以便在一个对象中看到发票类型,例如,不正确。

是否有一些工具/方法可以改善这种情况,以便在比较失败的情况下,我的测试报告会显示相当清晰简洁的输出? 也许我应该使用其他一些具有更多工具/功能的测试框架?

4 个答案:

答案 0 :(得分:1)

实现自己的断言方法。

import static org.junit.Assert.assertEquals;
...
public static void assertEquals(Invoice expected, Invoice actual) {
    assertEquals("invoiceDate", expected.invoiceDate, actual.invoiceDate);
    assertEquals("netPrice", expected.netPrice, actual.netPrice);
    assertEquals("invoiceRows", expected.invoiceRows, actual.invoiceRows);
    // and so on...
}

答案 1 :(得分:0)

“assertEquals”不知道哪个属性导致不相等的结果。 JUnit只为对象调用“equals”并检查布尔结果。

如果您想知道哪个属性不同,则需要逐个比较属性。

或者你可以实现正确的“toString”方法并比较字符串,结果你将能够看到不同的对象。

答案 2 :(得分:0)

您可能需要查看assertJ。特别是:

  • assertThat(预期).isEqualToComparingFieldByField(其他);
  • assertThat(预期).isEqualToComparingFieldByFieldRecursively(其他);
  • assertThat(预期).isEqualToComparingOnlyGivenFields(其他, “FIELD1”);
  • assertThat(预期).isEqualToIgnoringNullFields(其他)​​;

示例代码:

@Test
public void assertJTest() {
    Invoice expected = new Invoice();
    Invoice other = new Invoice();
    expected.setInvoiceNumber("123");
    other.setInvoiceNumber("456");
    expected.setNestedSet(singleton("12345"));
    other.setNestedSet(singleton("12346"));
    assertThat(expected).isEqualToIgnoringNullFields(other);
}

输出:

java.lang.AssertionError: 
Expecting values:
  <["123", ["12346"]]>
in fields:
  <["invoiceNumber", "nestedSet"]>
but were:
  <["456", ["12345"]]>
in <Invoice(nestedSet=[12345], invoiceNumber=123)>.
Comparison was performed on all fields

答案 3 :(得分:0)

Assert.assertEquals()会调用.equals()方法。最好的解决方案是推出自己的解决方案:

public class Invoice {

    ...

    @Override
    public boolean equals(Object o) {
        Invoice that = (Invoice) o;
        int errors = 0;

        // compare each field one at a time
        if(!this.invoiceDate.equals(that.invoiceDate) {
            log.error(String.format("invoiceDate are not equal: expected %s, actual %s!", this.invoiceDate, that.invoiceDate)
            errors++;
        }

        // you also have the option to do something fancy, like ignore null fields:
        if(this.invoiceNumber != null && that.invoiceNumber != null) {
            if(!this.invoiceNumber.equals(that.invoiceNumber) {
                log.error(String.format("invoiceNumber are not equal: expected %s, actual %s!", this.invoiceDate, that.invoiceDate)
                errors++;
            }
        }

        // continue with all other fields ...

        return errors == 0;
    }
}