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 AST
在 groovy web console 中自己查看转换后的代码。
我对用 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 AST
在 groovy web console 中自己查看转换后的代码。