存根方法应根据Spock中给定的模拟参数返回值

时间:2018-07-03 08:29:21

标签: groovy mocking spock stub

我希望有不同的返回结果-取决于方法的给定模拟参数。请考虑以下代码片段以符合我的意图

class ExampleSpec extends Specification {

    def "should return second value of list of return values"() {
        given:
        Person personBob = Mock()
        Person personJackson = Mock()
        PersonHelper stubbedPerson = Stub()

        stubbedPerson.getNameOfBrother(personBob) >> "Billy Bob";
        stubbedPerson.getNameOfBrother(personJackson) >> "Tommy Jackson";

        when:
        String actual = stubbedPerson.getNameOfBrother(personBob)
        String actual2 = stubbedPerson.getNameOfBrother(personJackson)

        then:
        actual == "Billy Bob" // true
        actual2 == "Tommy Jackson" // false "Billy Bob"
    }

}

测试失败,因为第二次调用var actual2仍然返回 Billy Bob ,而不是 Tommy Jackson 。我知道有一种方法可以按调用顺序返回不同的值,但我想使其依赖于给定的模拟。

使用正常值-无模拟/存根代理-参数值确实有效。我假设Spock引擎在两个模拟之间不会有所不同。但是我不确定,因为代理确实具有ID作为实例字段。

1 个答案:

答案 0 :(得分:3)

为了记录-使用模拟对象存根有效。我在您的示例中添加了简单的PersonPersonHelper类,并且测试通过了:

import spock.lang.Specification

class ExampleSpec extends Specification {

    def "should return second value of list of return values"() {
        given:
        Person personBob = Mock()
        Person personJackson = Mock()
        PersonHelper stubbedPerson = Stub()

        stubbedPerson.getNameOfBrother(personBob) >> "Billy Bob";
        stubbedPerson.getNameOfBrother(personJackson) >> "Tommy Jackson";

        when:
        String actual = stubbedPerson.getNameOfBrother(personBob)
        String actual2 = stubbedPerson.getNameOfBrother(personJackson)

        then:
        actual == "Billy Bob" // true
        actual2 == "Tommy Jackson" // false "Billy Bob"
    }

    static class Person {
        String name
    }

    static class PersonHelper {
        String getNameOfBrother(Person person) {
            return null
        }
    }
}

我已经用spock-core:1.1-groovy-2.4spock-core:1.0-groovy-2.4甚至spock-core:0.7-groovy-2.0进行了检查。一切正常。

但是更重要的是-这种测试没有任何意义。您根本不需要测试代码。您仅测试模拟框架是否正确模拟。如果您在生产代码中使用Spock模拟,则此测试可能会有所道理,但这不是有效的假设。

  

可能出什么问题了?

     

想想一下这个测试。根据您的when:块,您正在尝试测试PersonHelper.getNameOfBrother(Person person)是否为两个不同的对象返回有效的Brother名称。现在,假设这是项目中PersonHelper类的唯一测试。想象一下,如果getNameOfBrother方法的突然实现由于某种随机原因而开始抛出NullPointerException,会发生什么。问问自己-单元测试是否可以保护您免受这种情况的侵害?不。您的测试始终通过,因为您正在存根要测试的方法。如果您改为测试一个真实的实现,并传递一个真实的Person对象,那么您将在测试中收到有关NullPointerException的通知。否则,当您部署代码时,您将看到它,并且某些用户的操作调用此方法,它将失败。