我正在使用Spock框架编写测试,并且在测试列表相等时发现了一个奇怪的bavior。
当我比较像
这样的两个列表时sourceList == targetList
并且这些列表包含相同类型的Comparable对象,使用compareTo方法而不是equals来测试这些对象是否相等。
在这些列表上测试相等性时,有什么简单的方法可以强制Groovy使用equals吗?
这是一个简单的测试规范,其中测试应该失败,但事实并非如此。
class Test extends Specification {
def "list test"() {
when:
def listA = [[index: 1, text: "1"] as Bean, [index: 2, text: "2"] as Bean]
def listB = [[index: 1, text: "1"] as Bean, [index: 2, text: "3"] as Bean]
then:
listA == listB
}
class Bean implements Comparable<Bean> {
int index
String text
@Override
public int compareTo(Bean o) {
return index.compareTo(o.index);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + index;
result = prime * result + ((text == null) ? 0 : text.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Bean)) {
return false;
}
Bean other = (Bean) obj;
if (index != other.index) {
return false;
}
if (text == null) {
if (other.text != null) {
return false;
}
} else if (!text.equals(other.text)) {
return false;
}
return true;
}
}
}
答案 0 :(得分:0)
要求简单方法是主观的。这个答案的关键是,在Groovy中,is()
方法将check object equality。
在ArrayList
上考虑这个新方法。如果合适,它会将两个列表压缩在一起,并在每对项目上调用is()
。
ArrayList.metaClass.myCompare = { listB ->
def result = false
def listA = delegate
if (listB && listA.size() == listB.size()) {
def zipped = [listA, listB].transpose()
result = zipped.inject(true){ ok, pair ->
ok && pair[0].is(pair[1])
}
}
result
}
然后:
def beanA = new Bean(index: 1, text: 'a')
def beanA1 = new Bean(index: 1, text: 'a')
def beanB = new Bean(index: 2, text: 'b')
assert [beanA, beanB].myCompare([beanA, beanB])
assert ! [beanA, beanB].myCompare([beanA1, beanB])
assert ! [beanA, beanB].myCompare([beanA])
assert ! [beanA, beanB].myCompare(null)
assert ! [beanA, beanB].myCompare([])