【问题标题】:Spock set list as parameter by using tableSpock 使用表设置列表作为参数
【发布时间】:2018-03-20 12:28:55
【问题描述】:

有一个简单的类:

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 对象列表,然后检查该方法是否返回正确的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
}

我只是想用表格来设置参数,但我可能完全错了。

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

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

【问题讨论】:

  • 模拟简单的 pojo 是不好的做法,使用 bean 构造函数可以达到相同的效果,例如,["AA","BB"].collect{ new Person(name: it) }

标签: java testing groovy junit spock


【解决方案1】:

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 块中的双括号。它必须以这种方式指定,因为如果只使用单个对,每个单个参数都将单独传递,而不是传递整个列表。

【讨论】:

  • @tombobby,您的第一个示例运行良好,当使用此语法时,b 中不需要额外的括号,只需使用单个。第二个例子是两种方法的混合,这在设计上是无效的。
  • 不幸的是第一个解决方案不起作用(我再次编辑了我的帖子并在那里放了详细信息)
  • @tombobby,请再次阅读我之前的评论。在第一个解决方案中,b 不需要双括号。只需使用单个,所以:["AA", "BB"]["CC"]["DD","EE","FD"]
【解决方案2】:

您实际上可以将数据表与变量赋值 (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。

【讨论】:

  • 你能举例说明如何为对象添加一些值吗?在这个例子中,如何将name(和你一样)和age 放到每个对象上?
  • @tombobby 我不明白你想要什么?你问这个:groovy-lang.org/…你可以做这样的事情[[name: "AA", age: 18], [name: "BB", age: 20]].collect {new Person(it)}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-06
  • 2014-05-03
  • 2018-03-09
  • 1970-01-01
  • 2011-06-26
  • 1970-01-01
相关资源
最近更新 更多