Spock 测试中的 MissingPropertyException

MissingPropertyException in Spock test

我对用 groovy 编写的测试有疑问(使用 Spock 作为框架)。当我尝试在 then 块中获取 属性 然后在交互中使用它时,我在与事件发布者的交互中收到 No such property: updatedValue for class: my.test.class.MyTestClass。谁能告诉我这是为什么?

class MyTestClass extends Specification {


@Autowired
private MyClass sut

@Autowired
private MyClassRepository myClassRepository


@SpringBean
private EventPublisher eventPublisher = Mock()


def "Should do something"() {
    given:
    //some data
    def someId = "someId"
    def event = new SomeEventObject()

    when:
    sut.handle(event)

    then:
    def updatedValue = myClassRepository.findTestClass(someId)
    updatedTestClass.cash == 100

    1 * eventPublisher.publishEvent(new SomeNextEvent(updatedValue))
}
}

您遇到了 Spock 魔法的副作用。

你的方法基本上变成了这样:

public void $spock_feature_0_0() {
        org.spockframework.runtime.ErrorCollector $spock_errorCollector = org.spockframework.runtime.ErrorRethrower.INSTANCE
        org.spockframework.runtime.ValueRecorder $spock_valueRecorder = new org.spockframework.runtime.ValueRecorder()
        java.lang.Object someId = 'someId'
        java.lang.Object event = new apackage.SomeEventObject()
        this.getSpecificationContext().getMockController().enterScope()
        this.getSpecificationContext().getMockController().addInteraction(new org.spockframework.mock.runtime.InteractionBuilder(25, 9, '1 * eventPublisher.publishEvent(new SomeNextEvent(updatedValue))').setFixedCount(1).addEqualTarget(eventPublisher).addEqualMethodName('publishEvent').setArgListKind(true, false).addEqualArg(new apackage.SomeNextEvent(updatedValue)).build())
        sut.handle(event)
        this.getSpecificationContext().getMockController().leaveScope()
        java.lang.Object updatedValue = myClassRepository.findTestClass(someId)
        try {
            org.spockframework.runtime.SpockRuntime.verifyCondition($spock_errorCollector, $spock_valueRecorder.reset(), 'updatedTestClass.cash == 100', 23, 13, null, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(3), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(1), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(0), updatedTestClass).cash) == $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(2), 100)))
        }
        catch (java.lang.Throwable throwable) {
            org.spockframework.runtime.SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, 'updatedTestClass.cash == 100', 23, 13, null, throwable)}
        finally {
        }
        this.getSpecificationContext().getMockController().leaveScope()
    }

如果仔细观察,您会发现交互定义已移至 when 块之前,但 findTestClass() 调用保留在后面。 这就是为什么你得到丢失的 属性 异常。

解决方案是将查找移动到 given 块,或者如果这不可能,则使用参数捕获然后再检查。

given:
def capturedEvent

when:
...

then:
1 * eventPublisher.publishEvent(_) >> { capturedEvent = it[0} }

and:

def updatedValue = myClassRepository.findTestClass(someId)
capturedEvent instanceof SomeNextEvent
capturedEvent.value == updatedValue 

您可以通过单击 Inspect ASTgroovy web console 中自己查看转换后的代码。