Spock 测试框架:mock.getProperty('name') 与 getName() 的区别

3

在模拟实例中,getProperty('name')和getName()有什么区别?我以为它们的意思是一样的,但是有时候spock不满意其中一个,所以我不得不在它们之间切换。

假设我有以下类:

class Person {
    String name
}

我正在测试另一个旨在更新人员的类,所以我可以像这样做:

void "test something"() {
    Person personMock = Mock(Person)

    when:
    someObject.updatePersonName(personMock, 'new name')

    then:
    1 * personMock.getName() >> 'old name'
    1 * personMock.setName('new name')
}

简化测试的细节并不重要,重要的是我要验证某个属性是否被读取和更新。有时当我运行测试时会收到投诉,说personMock.getName()从未被调用,并且它很贴心地显示了personMock.getProperty('name')被调用。如果我重写测试来使用那种形式,测试就通过了。直到一段时间后,它再次抱怨getProperty('name')没有被调用,而是getName()。
我知道Spock不可能如此容易出错。我一定犯了错误。那么我应该在什么情况下使用getName(),在什么情况下使用getProperty('name')呢?
1个回答

0

你的代码出现了翻转,然而如果你正在测试 Groovy 代码,那么你应该使用 GroovyMock 而不是 Mock(也可以参见docs),它对一些 Groovy 的特殊功能提供了额外的支持。

何时应优先选择 Groovy Mocks 而非普通 Mocks? 在规范的代码是用 Groovy 编写的并且需要一些独特的 Groovy mock 功能时,应使用 Groovy mocks。当从 Java 代码中调用时,Groovy mocks 将像普通 mocks 一样运行。请注意,仅因为规范的代码和/或模拟类型是用 Groovy 写的,并不一定需要使用 Groovy mock。除非有明确的理由要使用 Groovy mock,否则请优先选择普通 mock。

在这种情况下,您(或您的代码)使用了一些Groovy的特殊功能,即Groovy MOP方法getPropertyGroovyMock使用GroovyMockInterceptor处理这些特殊方法,例如将getProperty('x')规范化为getX()
void "test something"() {
    Person personMock = GroovyMock(Person)

    when:
    someObject.updatePersonName(personMock, 'new name')

    then:
    1 * personMock.getName() >> 'old name'
    1 * personMock.setName('new name')
}

是的,我正在测试Groovy代码。感谢您关于GroovyMock的提示。 - Macoshark
很难说,因为这是一个间歇性的问题。Spock文档对此有如下说明:“请注意,仅因为规范代码和/或模拟类型是用Groovy编写的,并不意味着必须使用Groovy模拟。除非您有充分的理由使用Groovy模拟,否则请优先考虑使用常规模拟。”我将尝试使用GroovyMock,但我不会立即知道它是否解决了问题。 - Macoshark
您可以查看 https://github.com/spockframework/spock/blob/master/spock-core/src/main/java/org/spockframework/mock/runtime/GroovyMockInterceptor.java ,它将getProperty 调用映射到正确的 getter 方法,即规范化调用以始终在模拟对象上使用getter。这不是由 JavaMockInterceptor 完成的。因此,在引用您引用之前的文档中适用该句话:“需要一些独特的 Groovy 模拟功能”,即处理 Groovy MOP 方法。 - Leonard Brünings

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接