Spock 使用 table 将列表设置为参数

Spock set list as parameter by using table

有一个简单的 class:

class Person {
   private int age;
   private String name;

   public String getName(){return this.name;}
   public int getAge(){return this.age;}
   public void setName(String name){this.name = name;}
   public void setAge(int age){this.age = age;}
 }

并且我在 SearchPeople 接口中有方法 getPersonNameWithPrefix()getPeopleNames(),在 SearchPeopleImpl 中实现:

class SearchPeopleImpl implements SearchPeople {

   public String getPersonNameWithPrefix(Person person){
      return "prefix" + person.getName();
   }

   public List<String> getPeopleNames(List<Person> peopleList){
      return peopleList.stream().map(Person::getName).collect(Collectors.toList());
   }

}

我想在我的测试中使用参数,它看起来像:

def 'test Person name'(){
        given:
            def searchPeople = new SearchPeopleImpl ()
            def person = Mock(Person){
                getName() >> a
            }
        when:
            def name = searchPeople.getPersonNameWithPrefix(person)
        then:
            name == b
        where:
            a         |       b
            "AA"      |       "prefixAA"
            "BB"      |       "prefixBB"
            "CC"      |       "prefixCC"
    }

效果很好,但我在测试第二种方法时遇到了问题。如何将元素列表放入 table (在 where 部分),将其用作方法参数,然后期望另一个对象列表?我的意思是我想声明一些 Person 对象列表,然后检查该方法 returns 正确的 Strings

列表

@更新 那么有什么办法可以做这样的事情:

   def 'test getting persons names'(){
        given:
            def searchPeople = new SearchPeopleImpl()
        when:
            def names = searchPeople.getPeopleNames(a)
        then:
            names == b
        where:
            a                                                                  |       b
            ["AA","BB"].collect{ x -> Mock(Person){ getName() >> x } }         |       [["AA", "BB"]]
            ["CC"].collect{ x -> Mock(Person){ getName() >> x } }              |       [["CC"]]
            ["DD","EE","FD"].collect{ x -> Mock(Person){ getName() >> x } }    |       [["DD","EE","FD"]]
    }

或:

def 'check double2 return value'(){
    given:
        def searchPeople = new SearchPeopleImpl()
    when:
        def names = searchPeople.getPeopleNames(a)
    then:
        names == b
    where:
        people1 << [
                ["AA","BB"].collect{ x ->
                    Mock(Person){
                        getName() >> x
                    }
                }
        ]
        people2 << [
                ["CC"].collect{ x ->
                    Mock(Person){
                        getName() >> x
                    }
                }
        ]

        names1 << [["AA", "BB"]]
        names2 << [["CC"]]

        a               |       b
        people1         |       names1
        people2         |       names2
}

我只想用table设置参数,但有可能我完全错了。

@UPDATE 有一个错误:

check double return value[0](com.test.myPlugin.api.SearchPeopleSpec)  Time elapsed: 0.125 sec  <<< FAILURE!
Condition not satisfied:

names == b
|    |  |
|    |  [[AA, BB]]
|    false
[AA, BB]

并且每一行都有相同的错误。

List 的实例可以在数据驱动测试中以完全相同的方式使用。看看下面的例子:

class PersonSpec extends Specification {

    def 'test getting persons names'() {
        given:
        def searchPeople = new SearchPeopleImpl()

        when:
        def result = searchPeople.getPeopleNames(names)

        then:
        result == expectedNames

        where:
        names << [
            ["AA", "BB"].collect { n ->
            Mock(Person) {
                getName() >> n
            }
        }
        ]
        expectedNames << [["AA", "BB"]]
    }
}

注意 where 块中的双括号。它必须以这种方式指定,因为如果只使用一对,每个参数将单独传递而不是传递整个列表。

您实际上可以将数据表与变量赋值 (docs) 结合起来,从而提供更清晰的测试:

def 'test getting persons names'(){
    given:
    def searchPeople = new SearchPeopleImpl()

    when:
    def names = searchPeople.getPeopleNames(input)

    then:
    names == expected

    where:
    a                   |       expected
    ["AA","BB"]         |       [["AA", "BB"]]
    ["CC"]              |       [["CC"]]
    ["DD","EE","FD"]    |       [["DD","EE","FD"]]

    input = a.collect{ new Person(name: it) }
}

此外,如果您需要验证,请仅使用 Mock,例如,如果您仅将其用作协作者,请使用 1 * mock.method(),而不是使用 Stub 来明确您的意图。此外,当您可以通过 bean 构造函数构造它们时,切勿模拟简单的 POJO。