我希望有不同的返回结果-取决于方法的给定模拟参数。请考虑以下代码片段以符合我的意图
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作为实例字段。
答案 0 :(得分:3)
为了记录-使用模拟对象存根有效。我在您的示例中添加了简单的Person
和PersonHelper
类,并且测试通过了:
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.4
,spock-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
的通知。否则,当您部署代码时,您将看到它,并且某些用户的操作调用此方法,它将失败。