我想测试两个对象的相等性,但是对于它们的某些嵌套属性上存在的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));
}
}
是我希望对双打精度应用此判断的地方。
答案 0 :(得分:1)
这里的问题是Bar
有一个被覆盖的equals
方法,用于比较Bar
个实例,javadoc中提到了这一点(但我得到了javadoc并不总是发现API的最佳方式:
递归属性/字段比较不适用于具有自定义等于实现的字段,即将使用重写的equals方法而不是字段比较字段。
https://github.com/joel-costigliola/assertj-core/issues/1002是修改递归比较api的一张票,它已经过时了,它会提供强制递归比较的选项,即使equals
被覆盖(可能是forcingRecursiveComparisonForAll
)。< / p>