CucumberBackendException:没有测试实例



我有一个使用Cucumber BOM 7.4.1的Spring Boot 2.7.1项目(但2.6.4也是如此)。

testImplementation(platform("io.cucumber:cucumber-bom:7.4.1"))
testImplementation group: 'io.cucumber', name: 'cucumber-java8'
testImplementation group: 'io.cucumber', name: 'cucumber-spring'
testImplementation group: 'io.cucumber', name: 'cucumber-junit-platform-engine'

我的切入点是:

@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("features")
@ConfigurationParameters({
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "my.project.cucumber"),
@ConfigurationParameter(key = FILTER_TAGS_PROPERTY_NAME, value = "@Dwh"),
@ConfigurationParameter(key = JUNIT_PLATFORM_NAMING_STRATEGY_PROPERTY_NAME, value = "long"),
@ConfigurationParameter(key = PLUGIN_PUBLISH_QUIET_PROPERTY_NAME, value = "true"),
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "json:build/cucumber/cucumber.json")
})
public class RunCucumberDwhTest {
}

我的胶水代码:

@SpringBootTest(classes = DwhE2EApplication.class, webEnvironment = RANDOM_PORT)
@ContextConfiguration(classes = DwhE2EApplication.class)
@CucumberContextConfiguration
@ActiveProfiles("test")
public class DwhStepDef implements En {
....
}

当运行Cucumber测试时,我得到了这个错误:

io.cucumber.core.backend.CucumberBackendException:没有测试实例在app//io.cuckle.spring.TestContextAdaptor.notifyTestContextManagerAboutAfterTestMethod(TestContextAdaptor.java:129)在app//io.cuckle.spring.TestContextAdaptor.stop(TestContextAdaptor.java:109)在app//io.cuckles.spring.SpringFactory.stop(SpringFactory.java:159)在app//io.cuckle.core.runner.runner.disposeBackendWorlds(runner.java:156)在app//io.cuckle.core.runner.runPickle(runner.java:78)app//io.cuckle.junit.platform.engine.CuccumberEngineExecutionContextLambda$runTestCase$4(CucumberEngineExecutionContext.java:112)在app//io.cocumber.core.runtime.CuccumberExecutionContextLambda$runTestCase$5(CucumberExecution_Context.java:129)在app//io.cuckle.core.runtime.RetrowingThrowableCollector.executeAndThrow(RethrowingThrewableCollector.java:23)在app//io.cuckle.core.runtime.CuberExecutionContext.runTestCase(CucumberExecutionContext.java:129)在app//io.cuckle.junit.platform.engine.CuccumberEngineExecutionContext.runTestCase(CucumberEngineExecutionContext.java:109)在app//io.cuckle.junit.platform.engine.PickleDescriptor.execute(PickleDescriptor.java:100)在app//io.cuckle.junit.platform.engine.PickleDescriptor.execute(PickleDescriptor.java:29)在app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$6(NodeTestTask.java:151)在app//org.junit.platform.engine.support.hhierarchy.ThrowableCollectioner.execute(ThrowableCollector.java:73)在app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$8(NodeTestTask.java:141)在app//org.junit.platform.engine.support.histrared.Node.around(Node.java:137)在app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$9(NodeTestTask.java:139)在app//org.junit.platform.engine.support.hhierarchy.ThrowableCollectioner.execute(ThrowableCollector.java:73)在app//org.junit.平台.引擎.支持.层次结构.节点测试任务.执行执行(节点测试任务.java:138)在app//org.junit.平台.引擎.支持.层次结构.节点测试任务.执行(节点测试任务.java:95)在java.base@17.0.1/java.util.ArrayList.forEach(ArrayList.java:1511)在app//org.junit.platform.engine.support.hhierarchical.SameThreadHierarchicalTestExecutiorService.invokeAll(SameThreadHierarchialTestExecutiorServices.java:41)在app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$6(NodeTestTask.java:155)在app//org.junit.platform.engine.support.hhierarchy.ThrowableCollectioner.execute(ThrowableCollector.java:73)在app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$8(NodeTestTask.java:141)在app//org.junit.platform.engine.support.histrared.Node.around(Node.java:137)在app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$9(NodeTestTask.java:139)在app//org.junit.platform.engine.support.hhierarchy.ThrowableCollectioner.execute(ThrowableCollector.java:73)在app//org.junit.平台.引擎.支持.层次结构.节点测试任务.执行执行(节点测试任务.java:138)在app//org.junit.平台.引擎.支持.层次结构.节点测试任务.执行(节点测试任务.java:95)在java.base@17.0.1/java.util.ArrayList.forEach(ArrayList.java:1511)在app//org.junit.platform.engine.support.hhierarchical.SameThreadHierarchicalTestExecutiorService.invokeAll(SameThreadHierarchialTestExecutiorServices.java:41)在app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$6(NodeTestTask.java:155)在app//org.junit.platform.engine.support.hhierarchy.ThrowableCollectioner.execute(ThrowableCollector.java:73)在app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$8(NodeTestTask.java:141)在app//org.junit.platform.engine.support.histrared.Node.around(Node.java:137)在app//org.junit.platform.engine.support.histrared.NodeTestTaskLambda$executeSecurive$9(NodeTestTask.java:139)在app//org.junit.platform.engine.support.hhierarchy.ThrowableCollectioner.execute(ThrowableCollector.java:73)在app//org.junit.平台.引擎.支持.层次结构.节点测试任务.执行执行(节点测试任务.java:138)在app//org.junit.平台.引擎.支持.层次结构.节点测试任务.执行(节点测试任务.java:95)在app//org.junit.platform.engine.support.histrared.SameThreadHierarchicalTestExecutiorService.submit(SameThreadHierarchialTestExecutiorServices.java:35)在app//org.junit.platform.engine.support.hhierarchicalTestExecution.execute(HierarchicalTestExecution.java:57)在app//org.junit.platform.engine.support.hhierarchicalTestEngine.exexecute(HierarchicalTestEngine.java:54)在app//org.junit.platform.elauncher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrhestrator.java:107)在app//org.junit.platform.elauncher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrhestrator.java:88)在app//org.junit.platform.suite.engine.SuiteLauncher.execute(SuiteLauncher.java:59)在app//org.junit.platform.suite.engine.SuiteTestDescriptor.execute(SuiteTestDescriptor.java:130)在app//org.junit.platform.suite.engine.SuiteTestEngineLambda$execute$0(SuiteTestEngine.java:73)在java.base@17.0.1/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOperation.java:183)在java.base@17.0.1/java.util.stream.ReferencePipeline$3$1.accept(ReferencePiperine.java:197)在java.base@17.0.1/java.util.Iterator.forEachRemaining(Iterator.java:133)在java.base@17.0.1/java.util.Splitterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)在java.base@17.0.1/java.util.stream.AbstractPipeline.copyTinto(AbstractPipeline.java:509)在java.base@17.0.1/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)在java.base@17.0.1/java.util.stream.ForEachOps$ForEachOp.evalateSequential(ForEachOperation.java:150)在java.base@17.0.1/java.util.stream.ForEachOps$ForEachOp$OfRef.evalateSequential(ForEachOperation.java:173)在java.base@17.0.1/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)在java.base@17.0.1/java.util.stream.ReferencePipeline.forEach(ReferencePiperine.java:596)在app//org.junit.platform.suite.engine.SuiteTestEngine.exexecute(SuiteTestEngine.java:73)在app//org.junit.platform.elauncher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrhestrator.java:107)在app//org.junit.platform.elauncher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrhestrator.java:88)在app//org.junit.platform.selauncher.core.EngineExecutionOrchestratorLambda$execute$0(EngineExecutionOrhestrator.java:54)在app//org.junit.platform.selauncher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrhestrator.java:67)在app//org.junit.platform.elauncher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrhestrator.java:52)在app//org.junit.platform.selauncher.core.DefaultLauncher.execute(DefaultLauncher.java:114)在app//org.junit.platform.selauncher.core.DefaultLauncher.execute(DefaultLauncher.java:86)在app//org.junit.platform.slauncher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)在app//org.junit.platform.selauncher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)在org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasss(JUnitPlatformTestClassProcessor.java:99)在org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)在org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)在org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)在java.base@17.0.1/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(本机方法)java.base@17.0.1/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)在java.base@17.0.1/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)在java.base@17.0.1/java.lang.reflect.Method.ioke(Method.java:568)在org.gradle.internal.dispatch.ReflectionDispatch.dispatch(反射调度.java:36)在org.gradle.internal.dispatch.ReflectionDispatch.dispatch(反射调度.java:24)在org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)在org.grade.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)位于的jdk.proxy2/jdk.proxy2.$Proxy5.stop(未知源)org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)在org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintaineThreadName(TestWorker.java:129)在org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)在org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)在org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)在org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoader worker.java:133)在org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoader worker.java:71)在app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorker.Main.java:69)在app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorker main.java:74)引起原因:java.lang.IllegalStateException:处没有测试实例org.springframework.util.Assert.state(Assert.java:76)org.springframework.test.context.support.DefaultTestContext.getTestInstance(DefaultTestContext.java:160)在io.cuckle.spring.TestContextAdaptor.notifyTestContextManagerAboutAfterTestMethod(TestContextAdaptor.java:125)…还有89个

我可以在日志中看到,我的Spring上下文被加载,内存中的DB被引导。。。之后失败。

在调试模式下,我看到Given/Whin/Then步骤被捕获,所以我的功能文件肯定找到了。

事实上,当Cucumber在执行一个步骤后执行一些清理时,它似乎失败了:

io.cucumber.spring.TestContextAdaptor中的某个时刻,我们有一个被称为的方法

private void notifyTestContextManagerAboutAfterTestMethod() {
try {
Object delegateTestInstance = delegate.getTestContext().getTestInstance();
Method dummyMethod = TestContextAdaptor.class.getMethod("cucumberDoesNotHaveASingleTestMethod");
delegate.afterTestMethod(delegateTestInstance, dummyMethod, null);
} catch (Exception e) {
throw new CucumberBackendException(e.getMessage(), e);
}
}

delegate.getTestContext().getTestInstance()抛出异常,因为testInstance为null。

知道为什么会发生这种事吗?

在调试模式下进行了一些调查后,我终于明白了。我相信这是7.4.1黄瓜版本带来的变化,因为它在以前的版本中没有发生。我在这里报道过:https://github.com/cucumber/cucumber-jvm/issues/2584

基本上,我的粘合代码在实例化时抛出一个异常。但Cucumber并没有捕捉到异常,而是记录了一条完全无关的错误消息。

当我意识到我没有在粘合代码类中输入为步骤定义的代码时,我就明白了这一点。然后,我意识到我正在进入粘合代码构造函数,但从那里抛出了一个异常。这个例外被Cucumber默默地吞噬了,它把我推向了错误的方向,时间比预期的要长。