我第一次使用Spock。由于我们使用的是复杂的域模型,因此可以使用一种机制,这种机制允许我根据spock表给出的数据创建完整的对象。我不想每次都给出所有值,我只想设置datable中定义的值。所以应该在某处定义默认值。
是的,我知道我可以自己写,但也许有一个开箱即用的解决方案。
实施例
class A {
String name
int age
}
spock table
id | givenA | ...
1 | [name: "Michael"] | ...
2 | [name: "Thomas", age: 45 ] | ...
答案 0 :(得分:11)
在我拥有的每个项目中,我创造了我所称的' UnitTestUtils'此类主要包含辅助方法,这些方法使用默认值创建域对象,并允许覆盖这些值。例如:
Person createTestPerson(Map overrides = [:]){
Person p = new Person(name: "Jim Bob", age: 45)
overrides.each { String key, value ->
if(p.hasProperty(key)){
p.setProperty(key, value)
} else {
println "Error: Trying to add property that doesn't exist"
}
}
return p
}
然后,您可以通过以与您已经完成相同的方式创建地图,在课堂上使用此方法。
void "my test"(){
given:
Person person
when:
person = UnitTestUtils.createTestPerson(givenA)
then:
person.name == expected.name
person.age == expected.age
where:
id| givenA | expected
1 | [name: "Joe"] | [name: "Joe", age: 45]
2 | [age: 5] | [name: "Jim Bob", age: 5]
}
它不是内置的Spock功能,但它应该很好地为您指定的用例提供。
答案 1 :(得分:1)
基本上没有你正在寻找的机制。如果您需要为某些对象/字段提供默认值您需要自己动手并且没有任何奇怪,不好或不寻常的事情。请记住,测试代码的质量与生产代码一样重要,创建一些仅用于测试的帮助代码并不是一个坏习惯(当然,此代码仅存在于测试层次结构)。
在这种特殊情况下,而不是创建A
类您可以使用Map.withDefault
构造,但使用专用类的IMO要好得多。
答案 2 :(得分:1)
为什么不为此使用构建器模式?您可以提供一种方法,该方法将创建具有默认值的具体A对象,例如。
A.builder()
.withDefaults(HereAreDefaultValues.class)
.withName('Michael')
.build()
此示例使用单独的类来存储默认值,它应该在构建阶段复制所有这些属性。您也可以使用地图。
在这种情况下,任何稍后将阅读您的测试的人都将能够检查默认值是什么,并且如果在这些默认值发生更改时测试失败,则不会感到惊讶。您应该避免隐藏队友(甚至是您自己)的默认值等细节,因为这会使您的测试难以维护。 我知道,Builder示例更详细,但它作为软件的工件肯定更有用。
答案 3 :(得分:0)
不确定您究竟在寻找什么,但您可以写[name: "Thomas", age: 45]
而不是new A(name: Thomas, age: 45)
。如果你想重复使用灯具,你可以这样做:
where:
[id, givenA] << staticUtilityMethodThatReturnsCollectionOfTwoElementCollections()
您还可以创建一个小API(或使用Groovy的内置集合操作)来修改默认值。