Ответ прост - вы не можете. Спок использует преобразования AST, чтобы захватить код, написанный в части then:
, и преобразовать его в код, который эквивалентен утверждению (не точному assert
.)
Чтобы проиллюстрировать это, вот ваш тест написано в Споке:
import spock.lang.Specification
class TestSpec extends Specification {
def "should fail"() {
when:
def value = 42
then:
assert value == 100
}
}
И вот как выглядит его байт-код, декомпилированный обратно в Java:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.GroovyObject;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
import org.spockframework.runtime.ErrorCollector;
import org.spockframework.runtime.SpockRuntime;
import org.spockframework.runtime.ValueRecorder;
import org.spockframework.runtime.model.BlockKind;
import org.spockframework.runtime.model.BlockMetadata;
import org.spockframework.runtime.model.FeatureMetadata;
import org.spockframework.runtime.model.SpecMetadata;
import spock.lang.Specification;
@SpecMetadata(
filename = "TestSpec.groovy",
line = 5
)
public class TestSpec extends Specification implements GroovyObject {
public TestSpec() {
CallSite[] var1 = $getCallSiteArray();
super();
}
@FeatureMetadata(
line = 7,
name = "should fail",
ordinal = 0,
blocks = {@BlockMetadata(
kind = BlockKind.WHEN,
texts = {}
), @BlockMetadata(
kind = BlockKind.THEN,
texts = {}
)},
parameterNames = {}
)
public void $spock_feature_0_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);
Object var10000;
try {
Object value = 42;
try {
SpockRuntime.verifyCondition($spock_errorCollector, $spock_valueRecorder.reset(), "value == 100", Integer.valueOf(12), Integer.valueOf(16), (Object)null, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(2)), ScriptBytecodeAdapter.compareEqual($spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(0)), value), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(1)), 100))));
var10000 = null;
} catch (Throwable var14) {
SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, "value == 100", Integer.valueOf(12), Integer.valueOf(16), (Object)null, var14);
var10000 = null;
} finally {
;
}
var1[2].call(var1[3].call(this.getSpecificationContext()));
} finally {
$spock_errorCollector.validateCollectedErrors();
var10000 = null;
}
}
}
Если вы посмотрите на класс SpockRuntime
, вы найдете что метод verifyCondition
проверяет, соответствует ли условие, найденное в блоке then:
или and:
, true
:
public static void verifyCondition(@Nullable ErrorCollector errorCollector, @Nullable ValueRecorder recorder,
@Nullable String text, int line, int column, @Nullable Object message, @Nullable Object condition) {
if (!GroovyRuntimeUtil.isTruthy(condition)) {
final ConditionNotSatisfiedError conditionNotSatisfiedError = new ConditionNotSatisfiedError(
new Condition(getValues(recorder), text, TextPosition.create(line, column), messageToString(message), null, null));
errorCollector.collectOrThrow(conditionNotSatisfiedError);
}
}
Вы не можете избежать явного утверждения в тестах JUnit. Вы можете скрыть их в каком-нибудь вспомогательном методе, но вам все равно нужно вызвать их. Помните, что бегун JUnit требует, чтобы метод теста возвращал void
, поэтому вы не можете захватить результат метода теста. (Замените void
на def
, и вы увидите, что JUnit не запускает ваш тест.)
Если вы хотите исследовать мир метапрограммирования во время компиляции в Groovy, вы можете поэкспериментировать с написанием ваших собственных преобразований AST. Может быть, есть способ найти логическое выражение (выражения) и ввести перед ним assert
, но я не могу гарантировать вам, что это будет работать. Если вы ищете готовое решение для неявных утверждений в Groovy тестах JUnit, такого не будет.