Groovy Stubbed方法应该根据Spock中给定的mock参数返回值

Groovy Stubbed方法应该根据Spock中给定的mock参数返回值,groovy,mocking,spock,stub,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() Per

我希望有不同的返回结果-取决于方法的给定模拟参数。请考虑下面的代码片断来跟踪我的意图

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。我知道有一种方法可以通过调用顺序返回不同的值,但我希望它依赖于给定的mock


使用正常值(无模拟/存根代理)作为参数值确实有效。我假设斯波克引擎不能在两个模拟之间有所不同。但是我不确定这一点,因为代理确实有ID作为实例字段。

对于记录,使用模拟对象进行存根是可行的。我在您的示例中添加了简单的
Person
PersonHelper
类,测试通过:

导入spock.lang.Specification
类ExampleSpec扩展了规范{
def“应返回返回值列表中的第二个值”(){
鉴于:
Person personBob=Mock()
Person personJackson=Mock()
PersonHelper stubbedPerson=Stub()
stubbedPerson.getNameOfBrother(personBob)>>“billybob”;
stubbedPerson.getNameOfBrother(personJackson)>>“汤米·杰克逊”;
什么时候:
字符串实际值=stubbedPerson.getNameOfBrother(personBob)
String actual2=stubbedPerson.getNameOfBrother(personJackson)
然后:
实际值==“比利鲍勃”//true
实际值2==“汤米·杰克逊”//false“比利·鲍勃”
}
静态类人{
字符串名
}
静态类PersonHelper{
字符串getNameOfBrother(个人){
返回空
}
}
}
我已经用
spock-core:1.1-groovy-2.4
spock-core:1.0-groovy-2.4
甚至
spock-core:0.7-groovy-2.0
进行了检查。一切顺利

但更重要的是,这样的测试毫无意义。你根本不测试你的代码。您仅测试模拟框架是否正确模拟。如果在生产代码中使用Spock Mock,此测试可能会有一定意义,但这不是一个有效的假设

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