assertj中的usingComparatorForType似乎不适用于作为对象属性的对象的属性

时间:2018-05-22 14:41:53

标签: java assertj

我想测试两个对象的相等性,但是对于它们的某些嵌套属性上存在的double值的精度有一定的自由裁量权。 usingComparatorForType似乎是一个合适的解决方案,但如果我的Foo对象的类型为Bar,其中Bar.baz为{{1},那么它似乎无法正常工作我希望这种精确的自由裁量权适用于。 The example for isEqualToComparingFieldByFieldRecursively并未完全解决我尝试测试的情况。

一些示例代码

double

在这种情况下,import static org.assertj.core.api.Assertions.assertThat; import java.util.Comparator; import java.util.Objects; import org.junit.Test; public class ComparatorForTypeTest { private static final Comparator<Double> DOUBLE_COMPARATOR = new Comparator<Double>() { @Override public int compare(Double d1, Double d2) { return Math.abs(d1 - d2) <= 0.1 ? 0 : 1; } }; class Foo { private int id; private double baz; private Bar bar; public Foo(int id, double baz, Bar bar) { this.id = id; this.baz = baz; this.bar = bar; } public Foo withBar(Bar bar) { Foo that = this; that.bar = bar; return that; } @Override public int hashCode() { return Objects.hash(id, baz, bar); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } else if (obj == null || obj.getClass() != Foo.class) { return false; } Foo that = (Foo) obj; return Objects.equals(this.id, that.id) && Objects.equals(this.baz, that.baz) && Objects.equals(this.bar, that.bar); } @Override public String toString() { return String.format("Foo[id=%d, score=%f, bar=%s]", id, baz, bar == null ? null : bar.toString()); } } class Bar { private int id; private double baz; public Bar(int id, double baz) { this.id = id; this.baz = baz; } @Override public int hashCode() { return Objects.hash(id, baz); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } else if (obj == null || obj.getClass() != Bar.class) { return false; } Bar that = (Bar) obj; return Objects.equals(this.id, that.id) && Objects.equals(this.baz, that.baz); } @Override public String toString() { return String.format("Bar[id=%d, score=%f]", id, baz); } } @Test public void itComparesBars() { Bar a = new Bar(1, 1.4); Bar b = new Bar(1, 1.45); Bar c = new Bar(2, 1.4); assertThat(a).isNotEqualTo(b); assertThat(b).isNotEqualTo(c); assertThat(a).isNotEqualTo(c); assertThat(a).usingComparatorForType(DOUBLE_COMPARATOR, Double.class).isEqualToComparingFieldByField(b); } @Test public void itComparesFoos() { Foo a = new Foo(1, 1.4, null); Foo b = new Foo(1, 1.45, null); Foo c = new Foo(2, 1.4, null); assertThat(a).isNotEqualTo(b); assertThat(b).isNotEqualTo(c); assertThat(a).isNotEqualTo(c); assertThat(a).usingComparatorForType(DOUBLE_COMPARATOR, Double.class).isEqualToComparingFieldByField(b); Bar barA = new Bar(1, 1.4); Bar barB = new Bar(1, 1.45); assertThat(a.withBar(barA)).usingComparatorForType(DOUBLE_COMPARATOR, Double.class).isEqualToComparingFieldByFieldRecursively(b.withBar(barA)); assertThat(a.withBar(barA)).usingComparatorForType(DOUBLE_COMPARATOR, Double.class).isEqualToComparingFieldByFieldRecursively(b.withBar(barB)); } } 是我希望对双打精度应用此判断的地方。

1 个答案:

答案 0 :(得分:1)

这里的问题是Bar有一个被覆盖的equals方法,用于比较Bar个实例,javadoc中提到了这一点(但我得到了javadoc并不总是发现API的最佳方式:

  

递归属性/字段比较不适用于具有自定义等于实现的字段,即将使用重写的equals方法而不是字段比较字段。

https://github.com/joel-costigliola/assertj-core/issues/1002是修改递归比较api的一张票,它已经过时了,它会提供强制递归比较的选项,即使equals被覆盖(可能是forcingRecursiveComparisonForAll)。< / p>