比较两组不相等的 class
Compare two sets of a class without equals
我有一个class东西:
public class Something {
public String a;
public String b;
}
假设我无法在 class Something 中编写 equals 或 compare 方法。
我的测试:
Set<Something> aSet;
Set<Something> otherSet;
assertEquals(aSet, otherSet);//Fails because it only compares references of elements and does not perform a deep comparision field by field
是否有任何方法可以断言两个集合是否相等逐个比较元素(无需在 Something class 中编写 equals 方法)?
您可以使用 Hamcrest 库并执行
assertThat( aSet, both(everyItem(isIn(otherSet))).and(containsInAnyOrder(aSet)));
当我无法在遗留代码中实现 equals/hashCode
时,我遇到了类似的情况。
让我分享一个基于包装器模式的解决方案。您包装遗留 class 并在那里实施 equals/hashCode
。在您的测试中,您创建一组包装对象并按常规方式对其进行测试。
public class SomethingTest {
class SomethingWrapper {
private final Something value;
SomethingWrapper(Something value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SomethingWrapper that = (SomethingWrapper) o;
return new EqualsBuilder()
.append(value.a, that.value.a)
.append(value.b, that.value.b)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(value.a)
.append(value.b)
.toHashCode();
}
}
@Test
public void compareSomethingSetsWithoutEquals() {
final Set<Something> originalA = new HashSet<>();
originalA.add(new Something("a1", "b1"));
originalA.add(new Something("a2", "b2"));
final Set<Something> originalB = new HashSet<>();
originalB.add(new Something("a1", "b1"));
originalB.add(new Something("a2", "b2"));
final Set<SomethingWrapper> aWrappedSetA =
originalA.stream().map(SomethingWrapper::new).collect(Collectors.toSet());
final Set<SomethingWrapper> aWrappedSetB =
originalB.stream().map(SomethingWrapper::new).collect(Collectors.toSet());
assertEquals(aWrappedSetA, aWrappedSetB);
}
}
试试AssertJ,它提供了一种方法compare element field by field recursively,例子:
// the Dude class does not override equals
Dude jon = new Dude("Jon", 1.2);
Dude sam = new Dude("Sam", 1.3);
jon.friend = sam;
sam.friend = jon;
Dude jonClone = new Dude("Jon", 1.2);
Dude samClone = new Dude("Sam", 1.3);
jonClone.friend = samClone;
samClone.friend = jonClone;
assertThat(asList(jon, sam)).usingRecursiveFieldByFieldElementComparator()
.contains(jonClone, samClone);
另一种可能性是使用 specific element comparator 比较集合,因此 SomethingComparator
在您的情况下,这比第一个选项需要更多的工作,但您可以完全控制比较。
希望对您有所帮助!
我有一个class东西:
public class Something {
public String a;
public String b;
}
假设我无法在 class Something 中编写 equals 或 compare 方法。
我的测试:
Set<Something> aSet;
Set<Something> otherSet;
assertEquals(aSet, otherSet);//Fails because it only compares references of elements and does not perform a deep comparision field by field
是否有任何方法可以断言两个集合是否相等逐个比较元素(无需在 Something class 中编写 equals 方法)?
您可以使用 Hamcrest 库并执行
assertThat( aSet, both(everyItem(isIn(otherSet))).and(containsInAnyOrder(aSet)));
当我无法在遗留代码中实现 equals/hashCode
时,我遇到了类似的情况。
让我分享一个基于包装器模式的解决方案。您包装遗留 class 并在那里实施 equals/hashCode
。在您的测试中,您创建一组包装对象并按常规方式对其进行测试。
public class SomethingTest {
class SomethingWrapper {
private final Something value;
SomethingWrapper(Something value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SomethingWrapper that = (SomethingWrapper) o;
return new EqualsBuilder()
.append(value.a, that.value.a)
.append(value.b, that.value.b)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(value.a)
.append(value.b)
.toHashCode();
}
}
@Test
public void compareSomethingSetsWithoutEquals() {
final Set<Something> originalA = new HashSet<>();
originalA.add(new Something("a1", "b1"));
originalA.add(new Something("a2", "b2"));
final Set<Something> originalB = new HashSet<>();
originalB.add(new Something("a1", "b1"));
originalB.add(new Something("a2", "b2"));
final Set<SomethingWrapper> aWrappedSetA =
originalA.stream().map(SomethingWrapper::new).collect(Collectors.toSet());
final Set<SomethingWrapper> aWrappedSetB =
originalB.stream().map(SomethingWrapper::new).collect(Collectors.toSet());
assertEquals(aWrappedSetA, aWrappedSetB);
}
}
试试AssertJ,它提供了一种方法compare element field by field recursively,例子:
// the Dude class does not override equals
Dude jon = new Dude("Jon", 1.2);
Dude sam = new Dude("Sam", 1.3);
jon.friend = sam;
sam.friend = jon;
Dude jonClone = new Dude("Jon", 1.2);
Dude samClone = new Dude("Sam", 1.3);
jonClone.friend = samClone;
samClone.friend = jonClone;
assertThat(asList(jon, sam)).usingRecursiveFieldByFieldElementComparator()
.contains(jonClone, samClone);
另一种可能性是使用 specific element comparator 比较集合,因此 SomethingComparator
在您的情况下,这比第一个选项需要更多的工作,但您可以完全控制比较。
希望对您有所帮助!