Using spock data table for filling objects

10,359

Solution 1

In every project I have, I create what I call 'UnitTestUtils' and this class mostly contains helper methods that create domain objects with default values and allow for overrides of those values. For example:

    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
    }

Then you can make use of this method in your class by creating a map in the same way you've already done.

    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]
    }

It's not a built in Spock feature, but it should provide nicely for the use case you have specified.

Solution 2

Basically there's no such mechanism You're looking for. If You need to provide default values for some objects/fields You need to do it Yourself and there's nothing strange, bad or unusual about it. Remember that the quality of test code is as important as the production code and it's not a bad practice to create some helper code that is used for tests only (of course this code exists only in tests hierarchy).

In this particular case instead of creating A class You can use Map.withDefault construct, but IMO using a dedicated class is much better.

Share:
10,359
EhmKah a.k.a. Michael Krauße
Author by

EhmKah a.k.a. Michael Krauße

Updated on June 13, 2022

Comments

  • EhmKah a.k.a. Michael Krauße
    EhmKah a.k.a. Michael Krauße almost 2 years

    I am using Spock for the first time. Since we are using a complex domain-model it would be handy to have a mechanism, which allows me to create full objects from data given by spock tables. I do not want to give all values each time, I just want to set the values in defined in datable. So there should be defined default values somewhere.

    Yes, I know I could write on my own, but maybe there is an out-of-the-box solution.

    Example

    class A {
       String name
       int age
    }
    

    spock table

    id | givenA                     | ...
    1  | [name: "Michael"]          | ...
    2  | [name: "Thomas", age: 45 ] | ...
    
    1. => A.name = "Michael", A.age = defined default somewhere
    2. => A.name = "Thomas" A.age = 45 (because I overwrite default value)