Groovy 斯波克的魔力是什么;然后";块

Groovy 斯波克的魔力是什么;然后";块,groovy,spock,Groovy,Spock,我是Groovy/Spock新手,很想了解“then”块语法的秘密: def "my specification"() { given: int a = 1 when: ++a then: a == 1 a > 0 a != 2 } 框架如何分别评估此方法的最后3行?那么本身就是一个普通的旧Java标签 每一行都是一个新的调用>>Java的可以输入 每个调用都封装在Groovy的ass

我是Groovy/Spock新手,很想了解“then”块语法的秘密:

def "my specification"() {
    given:
        int a = 1
    when:
        ++a
    then:
        a == 1
        a > 0
        a != 2
}

框架如何分别评估此方法的最后3行?

那么
本身就是一个普通的旧Java标签

每一行都是一个新的调用>>Java的
可以输入

每个调用都封装在Groovy的
assert
语句中,该语句也可以在Spock之外执行:

int a = 1
assert a
assert 0 < a
assert !a // here assertion error
inta=1
断言
断言0
除了和所说的,下面是Fernflower反编译(在IntelliJ IDEA中完成)的以下规范的结果:

package de.scrum\u master.stackoverflow
导入spock.lang.Specification
类DummyTest扩展了规范{
def“我的规格”(){
鉴于:
int a=1
什么时候:
++a
然后:
a==2
a>1
a!=3
}
}
package de.scrum\u master.stackoverflow;
导入groovy.lang.GroovyObject;
导入org.codehaus.groovy.runtime.BytecodeInterface8;
导入org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
导入org.codehaus.groovy.runtime.callsite.callsite;
导入org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
导入org.spockframework.runtime.ErrorCollector;
导入org.spockframework.runtime.SpockRuntime;
导入org.spockframework.runtime.ValueRecorder;
导入org.spockframework.runtime.model.BlockKind;
导入org.spockframework.runtime.model.BlockMetadata;
导入org.spockframework.runtime.model.FeatureMetadata;
导入org.spockframework.runtime.model.SpecMetadata;
导入spock.lang.Specification;
@规范元数据(
filename=“DummyTest.groovy”,
直线=5
)
公共类DummyTest扩展规范实现GroovyObject{
公测{
CallSite[]var1=$getCallSiteArray();
超级();
}
@特性元数据(
直线=6,
name=“我的规格”,
序数=0,
blocks={@BlockMetadata(
种类=BlockKind.SETUP,
文本={}
),@BlockMetadata(
kind=BlockKind.WHEN,
文本={}
),@BlockMetadata(
那么,
文本={}
)},
参数名称={}
)
公共作废$spock\u功能\u 0\u 0(){
CallSite[]var1=$getCallSiteArray();
ErrorCollector$spock_ErrorCollector=(ErrorCollector)ScriptBytecodeAdapter.castToType(var1[0].callConstructor(ErrorCollector.class,false),ErrorCollector.class);
ValueRecorder$spock_ValueRecorder=(ValueRecorder)ScriptBytecodeAdapter.castToType(var1[1].callConstructor(ValueRecorder.class)、ValueRecorder.class);
对象VAR1000;
试一试{
INTA=1;
INTA;
if(字节码接口8.isOrigInt()&&&!uu$stMC&&!字节码接口8.disabledStandardMetaClass()){
a=a+1;
}否则{
a=DefaultTypeTransformation.intUnbox(var1[2]。调用(Integer.valueOf(a));
}
试一试{
SpockRuntime.verifyCondition($spock\u errorCollector,$spock\u valueRecorder.reset(),“a==2”,Integer.valueOf(12),Integer.valueOf(5),(Object)null,$spock\u valueRecorder.record($spock\u valueRecorder.startRecordingValue(Integer.valueOf(2)),ScriptBytecodeAdapter.CompareQual($spock\u valueRecorder.record($spock\u valueRecorder.startRecordingValue.startRecordingValue(Integer.valueOf(0)),a),$spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(1)),2));
var10000=null;
}捕获(可丢弃var44){
SpockRuntime.conditionFailedWithException($spock\u errorCollector,$spock\u valueRecorder,“a==2”,Integer.valueOf(12),Integer.valueOf(5),(Object)null,var44);
var10000=null;
}最后{
;
}
试一试{
SpockRuntime.verifyCondition($spock\u errorCollector,$spock\u valueRecorder.reset(),“a>1”,Integer.valueOf(13),Integer.valueOf(5),(Object)null,$spock\u valueRecorder.record($spock\u valueRecorder.startRecordingValue(Integer.valueOf(2)),ScriptBytecodeAdapter.CompareGraeterThan($spock\u valueRecorder.record($spock\u valueRecorder.startRecordingValue(Integer.valueOf(0)),a),$spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(1)),1));
var10000=null;
}捕获(可丢弃var42){
SpockRuntime.conditionFailedWithException($spock\u errorCollector,$spock\u valueRecorder,“a>1”,Integer.valueOf(13),Integer.valueOf(5),(Object)null,var42);
var10000=null;
}最后{
;
}
试一试{
SpockRuntime.verifyCondition($spock\u errorCollector,$spock\u valueRecorder.reset(),“a!=3”,Integer.valueOf(14),Integer.valueOf(5),(Object)null,$spock\u valueRecorder.record($spock\u valueRecorder.startRecordingValue(Integer.valueOf(2)),ScriptBytecodeAdapter.CompareNodeQual($spock\u valueRecorder.record($spock\u valueRecorder.startRecordingValue)(Integer.valueOf(0)),a),$spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(1)),3));
var10000=null;
}捕获(可丢弃var40){
SpockRuntime.conditionFailedWithException($spock\u errorCollector,$spock\u valueRecorder,“a!=3”,Integer.valueOf(14),Integer.valueOf(5),(Object)null,var40);
var10000=null;
}最后{
;
}
var1[3]。调用(var1[4]。调用(this.getSpecificationContext());
}最后{
$spock_errorCollector.validateCollectedErrors();
var10000=null;
}
}
}

Tim的链接为您提供了更多的背景信息。正如您所看到的,不仅仅是预加
assert
,它更像
SpockRuntime.verifyCondition(…)
包装在try-catch中。

有一篇@szymon stepniak写的非常好的博文,详细介绍了spock对then块所做的工作:这是一篇很好的阅读。我正在查看编译后的代码……感谢您的回答。您能精确地说明包装是如何发生的吗?@injecteer“每个调用都包装在Groovy的断言语句中t'是一个很好的近似值,但并非完全正确,请参见kriegaex答案了解实际发生的情况。