Search code examples
groovyspockassertions

How to compare similar field names in different type of objects in collections in Spock?


I have two collections of different types - eg. Fruit and Vegetable.

Now in spock I assert contents of those collections in one of the following ways:

fruits.size() == vegetables.size()
for (int i = 0; i < fruits.size(); i++) {
    assert fruits[i].name == vegetables[i].name
    assert fruits[i].active == vegetables[i].enabled
}

Is there any better way to compare such collections?


Solution

  • You can utilize Groovy's spread operator to extract list of values and compare those lists. Consider following example:

    class Fruit {
        String name
        boolean active
    }
    
    class Vegetable {
        String name
        boolean enabled
    }
    
    def fruits = [new Fruit(name: 'Apple', active: false), new Fruit(name: 'Tomato', active: true)]
    def vegetables = [new Vegetable(name: 'Apple', enabled: false), new Vegetable(name: 'Tomato', enabled: false)]
    
    assert fruits.name == vegetables.name
    assert fruits.active == vegetables.enabled
    

    First assertion passes, because:

    assert ['Apple', 'Tomato'] == ['Apple', 'Tomato']
    

    However second assertion fails, because:

    assert fruits.active == vegetables.enabled
           |      |      |  |          |
           |      |      |  |          [false, false]
           |      |      |  [Vegetable@5b8dfcc1, Vegetable@2f9f7dcf]
           |      |      false
           |      [false, true]
           [Fruit@747ddf94, Fruit@35e2d654]
    

    In this case you don't have to compare if both lists have the same size and also order of objects matters. The only downside is that values you extract to lists have to be comparable - otherwise it will compare references to objects.

    Finally, your Spock test could look like this:

    def "comparing fruits and vegetales"() {
        when:
        def fruits = initializeFruits()
        def vegetables = initializeVegetables()
    
        then:
        fruits.name == vegetables.names
    
        and:
        fruits.active == vegetables.enabled
    }