使用spock数据表填充对象

我是第一次使用Spock。 由于我们使用的是复杂的域模型,因此可以使用一种机制,这种机制允许我根据spock表给出的数据创建完整的对象。 我不想每次都给出所有值,我只想设置datable中定义的值。 所以应该在某处定义默认值。

是的,我知道我可以自己写,但也许有一个开箱即用的解决方案。

class A { String name int age } 

spock表

 id | givenA | ... 1 | [name: "Michael"] | ... 2 | [name: "Thomas", age: 45 ] | ... 
  1. => A.name =“Michael”,A.age =在某处定义默认值
  2. => A.name =“Thomas”A.age = 45(因为我覆盖了默认值)

在我拥有的每个项目中,我创建了我称之为’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] } 

它不是内置的Spockfunction,但它应该很好地为您指定的用例提供。

基本上没有你正在寻找的这种机制。 如果您需要为某些对象/字段提供默认值您需要自己动手并且没有任何奇怪,不好或不寻常的事情。 请记住,测试代码的质量与生产代码一样重要,创建一些仅用于测试的帮助程序代码并不是一个坏习惯(当然,此代码仅存在于测试层次结构中)。

在这种特殊情况下,而不是创建A类您可以使用Map.withDefault构造,但使用专用类的IMO要好得多。

为什么不为此使用Builder模式 ? 您可以提供一个方法来创建具有默认值的具体A对象,例如

 A.builder() .withDefaults(HereAreDefaultValues.class) .withName('Michael') .build() 

此示例使用单独的类来存储默认值,它应该在构建阶段复制所有这些属性。 您也可以使用Map来实现此目的。

在这种情况下,任何稍后将读取您的测试的人都将能够检查默认值是什么,并且如果在这些默认值发生更改时测试失败,则不会感到惊讶。 您应该避免隐藏队友(甚至是您自己)的默认值等细节,因为这会使您的测试难以维护。 我知道,Builder示例更详细,但它作为软件的工件肯定更有用。

不确定你究竟在寻找什么,但是你可以写出new A(name: Thomas, age: 45)而不是[name: "Thomas", age: 45] 。 如果您想重复使用灯具,您可以:

 where: [id, givenA] << staticUtilityMethodThatReturnsCollectionOfTwoElementCollections() 

您还可以创建一个小API(或使用Groovy的内置集合操作)来修改默认值。