为什么我要在Kotlin中运行这个特殊的Cucumber步骤来获得ArrayIndexOutOfBoundsException?
我正在运行一个Cucumber JVM特性文件,使用Java8和PicoContainer。我已经把这些台阶剥去了,所以它们是空的,但我仍然得到一个错误。以下是我的特色:为什么我要在Kotlin中运行这个特殊的Cucumber步骤来获得ArrayIndexOutOfBoundsException?,kotlin,bdd,cucumber-jvm,cucumber-java,picocontainer,Kotlin,Bdd,Cucumber Jvm,Cucumber Java,Picocontainer,我正在运行一个Cucumber JVM特性文件,使用Java8和PicoContainer。我已经把这些台阶剥去了,所以它们是空的,但我仍然得到一个错误。以下是我的特色: Feature: Full Journey Scenario: Can load a typical JIRA csv and calculate the distribution from it Given a typical JIRA export "/closed_only_JIRA.csv" When I impo
Feature: Full Journey
Scenario: Can load a typical JIRA csv and calculate the distribution from it
Given a typical JIRA export "/closed_only_JIRA.csv"
When I import it into Montecarluni
Then I should see the distribution
"""
6, 15, 3, 14, 2, 5, 6, 8, 5, 10, 15, 4, 2, 1
"""
When I copy it to the clipboard
Then I should be able to paste it somewhere else
(是的,这是一个完整的过程,而不是BDD场景。)
无论出于何种原因,在Kotlin中运行此步骤都会导致错误:
import cucumber.api.java8.En
class ClipboardSteps(val world : World) : En {
init {
When("^I copy it to the clipboard$", {
// Errors even without any code here
})
}
}
虽然该Java类运行良好:
import cucumber.api.java8.En;
public class JavaClipboardSteps implements En {
public JavaClipboardSteps(World world) {
When("^I copy it to the clipboard$", () -> {
// Works just fine with code or without
});
}
}
我完全困惑不解,尤其是因为Kotlin steps类中的“Then”运行得非常完美,而另一个步骤运行时没有错误:
import cucumber.api.java8.En
class FileImportSteps(val world: World) : En {
init {
// There's a Given here
When("^I import it into Montecarluni$", {
// There's some code here
})
}
}
跑步者,为了完成:
import cucumber.api.CucumberOptions
import cucumber.api.junit.Cucumber
import org.junit.runner.RunWith
@RunWith(Cucumber::class)
@CucumberOptions(
format = arrayOf("pretty"),
glue = arrayOf("com.lunivore.montecarluni.glue"),
features = arrayOf("."))
class Runner {
}
Stacktrace是:
cucumber.runtime.CucumberException: java.lang.ArrayIndexOutOfBoundsException: 52
at cucumber.runtime.java.JavaBackend.addStepDefinition(JavaBackend.java:166)
at cucumber.api.java8.En.Then(En.java:280)
at com.lunivore.montecarluni.glue.DistributionSteps.<init>(DistributionSteps.kt:8)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.picocontainer.injectors.AbstractInjector.newInstance(AbstractInjector.java:145)
at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:342)
at org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicDependencyGuard.observe(AbstractInjector.java:270)
at org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364)
at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.getComponentInstance(AbstractInjectionFactory.java:56)
at org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64)
at org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91)
at org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699)
at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647)
at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:678)
at cucumber.runtime.java.picocontainer.PicoFactory.getInstance(PicoFactory.java:40)
at cucumber.runtime.java.JavaBackend.buildWorld(JavaBackend.java:131)
at cucumber.runtime.Runtime.buildBackendWorlds(Runtime.java:141)
at cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:38)
at cucumber.runtime.junit.ExecutionUnitRunner.run(ExecutionUnitRunner.java:102)
at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:63)
at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:18)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at cucumber.runtime.junit.FeatureRunner.run(FeatureRunner.java:70)
at cucumber.api.junit.Cucumber.runChild(Cucumber.java:95)
at cucumber.api.junit.Cucumber.runChild(Cucumber.java:38)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at cucumber.api.junit.Cucumber.run(Cucumber.java:100)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 52
at jdk.internal.org.objectweb.asm.Type.getArgumentTypes(Type.java:358)
at cucumber.runtime.java8.ConstantPoolTypeIntrospector.getGenericTypes(ConstantPoolTypeIntrospector.java:32)
at cucumber.runtime.java.Java8StepDefinition.getParameterInfos(Java8StepDefinition.java:54)
at cucumber.runtime.java.Java8StepDefinition.<init>(Java8StepDefinition.java:44)
at cucumber.runtime.java.JavaBackend.addStepDefinition(JavaBackend.java:162)
... 44 more
cucumber.runtime.CucumberException:java.lang.ArrayIndexOutOfBoundsException:52
位于cucumber.runtime.java.JavaBackend.addStepDefinition(JavaBackend.java:166)
在cumber.api.java8.En.Then(En.java:280)
位于com.lunivore.montecarluni.glue.DistributionSteps.(DistributionSteps.kt:8)
位于sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法)
位于sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
在sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
位于java.lang.reflect.Constructor.newInstance(Constructor.java:423)
位于org.picocontainer.injectors.AbstractInjector.newInstance(AbstractInjector.java:145)
位于org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:342)
在org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicdDependencyGuard.observe上(AbstractInjector.java:270)
位于org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364)
位于org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.getComponentInstance(AbstractInjectionFactory.java:56)
位于org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64)
位于org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91)
位于org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699)
位于org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647)
位于org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:678)
在cucumber.runtime.java.picocontainer.picofacory.getInstance(picofacory.java:40)中
位于cucumber.runtime.java.JavaBackend.buildWorld(JavaBackend.java:131)
在cucumber.runtime.runtime.buildBackendWorlds(runtime.java:141)
在cucumber.runtime.model.cucumbersecenario.run(cucumbersecenario.java:38)
在cucumber.runtime.junit.ExecutionUnitRunner.run(ExecutionUnitRunner.java:102)中
在cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:63)中
在cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:18)中
位于org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
位于org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
位于org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
访问org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
位于org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
位于org.junit.runners.ParentRunner.run(ParentRunner.java:363)
运行(FeatureRunner.java:70)
cumber.api.junit.cumber.runChild(cumber.java:95)
cumber.api.junit.cumber.runChild(cumber.java:38)
位于org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
位于org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
位于org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
访问org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
位于org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
位于org.junit.runners.ParentRunner.run(ParentRunner.java:363)
位于cumber.api.junit.cumber.run(cumber.java:100)
位于org.junit.runner.JUnitCore.run(JUnitCore.java:137)
位于com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
位于com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
位于com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
位于com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
原因:java.lang.ArrayIndexOutOfBoundsException:52
位于jdk.internal.org.objectweb.asm.Type.getArgumentTypes(Type.java:358)
在cucumber.runtime.java8.ConstantPoolTypeIntrospector.getGenericTypes(ConstantPoolTypeIntrospector.java:32)
位于cucumber.runtime.java.Java8StepDefinition.GetParameterInfo(Java8StepDefinition.java:54)
在cucumber.runtime.java.Java8StepDefinition.(Java8StepDefinition.java:44)
位于cucumber.runtime.java.JavaBackend.addStepDefinition(JavaBackend.java:162)
... 44多
发生什么事了
当前使用Kotlin步骤签入的所有源代码都已注释掉。(请原谅这种混乱,因为我对我正在使用的很多东西都是新手;从最初的峰值开始重构正在进行。)这似乎是Kotlin编译匿名代码块的优化之间的一种不幸的交互,Cumber假设JVM如何存储对lambda的引用,Cucumber使用了一些不应该接近的JVM内部构件 由于各种(不同)原因,您的系统不会触发错误 简单地说,如果Kotlin可以实现一个块或lambda作为一个静态单例,那么它可以实现,大概是出于性能原因。这会干扰magic Cumber执行的一些非常规反射(详情如下) 修复方法是在Cucumber代码中添加一个额外的检查,尽管可以说更好的修复方法是重写Cucumber代码以供使用 解决方法是确保Kotlin不会通过包含对包含实例的引用来优化lambda。即使是像引用
这样简单的内容
:
When("^I import it into Montecarluni$") {
this
// your code
}
足以说服Kotlin不要进行优化
细节
Cucumber在中添加带有lambda的步骤定义时,例如。