我正在测试使用Library对象的SortedSet的类的行为(常规类不是接口,因此我引入了cglib-nodep)。当排序集有多个对象时,我需要测试类的行为。 Library对象已经以这种方式被嘲笑:
Library library = Mock()
Library library2 = Mock()
然后,我创建一个TreeSet:
def libraries = [library, library2] as TreeSet
并在测试方法下调用系统:
sut.doStuff(libraries).
当我调试此测试时,我看到库是一个只有一个元素的SortedSet。这似乎是Spock处理平等的方式的结果,如:
def "equality test"() {
expect:
library == library2
}
当我运行测试时,通过。有没有办法可以绕过这种行为?
编辑:将=更改为==因为我无法输入
答案 0 :(得分:3)
做了一些研究。看看下面的一组测试(groovy控制台脚本):
@Grab('org.spockframework:spock-core:0.7-groovy-2.0')
@Grab('cglib:cglib-nodep:3.1')
import spock.lang.*
class Test extends Specification {
def "not comparable mocks are not equal"() {
given:
def a1 = Mock(A)
def a2 = Mock(A)
expect:
a1.hashCode() != a2.hashCode()
!a1.equals(a2)
!(a1 == a2)
}
def "comparable mocks are not equal"() {
given:
def a1 = Mock(AC)
def a2 = Mock(AC)
expect:
a1.hashCode() != a2.hashCode()
!a1.equals(a2)
!(a1 == a2)
}
def "cannot create TreeSet when POJOs are not comparable"() {
given:
def a1 = Mock(A)
def a2 = Mock(A)
and:
a1.hashCode() != a2.hashCode()
!a1.equals(a2)
!(a1 == a2)
when:
new TreeSet([a1,a2])
then:
def e = thrown(ClassCastException)
e.message.endsWith('cannot be cast to java.lang.Comparable')
}
def "there's a problem with Comparable Mocks"() {
given:
def a1 = Mock(AC)
def a2 = Mock(AC)
and:
a1.hashCode() != a2.hashCode()
!a1.equals(a2)
!(a1 == a2)
when:
def s = new TreeSet([a1,a2])
then:
s.size() == 2
}
def "with HashSet it works as expected"() {
given:
def a1 = Mock(AC)
def a2 = Mock(AC)
and:
a1.hashCode() != a2.hashCode()
!a1.equals(a2)
!(a1 == a2)
when:
def s = new HashSet([a1,a2])
then:
s.size() == 2
}
}
class A {}
class AC implements Comparable {
int compareTo(Object o) {
1 //whatever value may be here, it's not called
}
}
通常,对象实现Comparable
接口时会出现问题。
Comparable
的事实除外。它失败。据我说,这不是预期的行为。TreeSet
。预期的行为。TreeSet
模拟创建的Comparable
的大小预计为2.它失败,大小为1. HashSet
时,符合4项测试的条件。 IMO这不是spock
相关的问题。 Spock使用cglib
作为mockin对象,这是应该寻找解释的地方。
修改强>
如果模拟对象覆盖compareTo()
方法,它可以正常工作:
@Grab('org.spockframework:spock-core:0.7-groovy-2.0')
@Grab('cglib:cglib-nodep:3.1')
import spock.lang.*
class Test extends Specification {
def "there's a problem with Comparable Mocks"() {
given:
def a1 = Mock(AC) {
compareTo(_) >> 3145
}
def a2 = Mock(AC) {
compareTo(_) >> 3146
}
and:
a1.hashCode() != a2.hashCode()
!a1.equals(a2)
!(a1 == a2)
when:
def s = new TreeSet([a1,a2])
then:
s.size() == 2
}
}
class AC implements Comparable {
int compareTo(Object o) {
1 //whatever value may be here, it's not called
}
}
答案 1 :(得分:3)
除非其equals()
方法被存根,否则只有Mock()
equals()
本身。但是,Groovy的==
并不总是equals()
。对于Comparable
,它意味着c1.compareTo(c2) == 0
。同样,TreeSet
使用compareTo()
而不是equals
来确定相等性。潜在的解决方案:
compareTo()
方法返回合适的值。TreeSet
。compareTo
而不是模拟的真实对象。 PS:Mock(Comparable)
和/或Stub(Comparable)
可能会以与compareTo
一致的方式自动实施equals()
。你可以为此提出问题吗?