英文:
Cucumber-JVM, Kotlin and Spring Configuration causing No Default Constructor error
问题
我有一个使用Cucumber for Java设置的项目,实际上是使用Kotlin,但在底层仍然使用Java。
它使用Spring进行依赖注入,并且具有以下配置,目前可以正常工作:
```java
package com.cucumberproject.projectA.hooks
import com.cucumberproject.projectA.profile.ProfileManager
import com.cucumberproject.projectA.profile.EnvironmentProfile
import org.springframework.context.annotation.Bean
class AppConfiguration {
@Bean
fun profileManager(): EnvironmentProfile {
return ProfileManager().getEnvProfile(
"clientId",
"clientSecret",
TokenUrl,
AuthorisationUrl);
}
}
package com.cucumberproject.projectA.hooks
import io.cucumber.java8.En
import org.springframework.test.context.ContextConfiguration
@ContextConfiguration(classes = [AppConfiguration::class])
class SetupSteps : En {
}
import com.cucumberproject.projectA.hooks.*
import com.cucumberproject.projectA.profile.EnvironmentProfile
import io.cucumber.java.PendingException
import io.cucumber.java.Scenario
import io.cucumber.java8.En
class FeatureSteps @Autowired constructor(private var profile: EnvironmentProfile) : En {
private lateinit var scenario: Scenario
@Before
fun initialise(scenario: Scenario) {
this.scenario = scenario
}
init {
Given("A certain state") {
// code in here that works
}
我正在尝试创建一个具有相同设置的新项目。它可以访问相同的AppConfiguration文件、EnvironmentProfile文件和SetupSteps文件,因为它们作为依赖项被引入。
package com.cucumberproject2.projectB.stepdefs
import com.cucumberproject.hooks.AppConfiguration //original project
import com.cucumberproject.hooks.SetupSteps //original project
import com.cucumberproject.stepdefs.ProgramSetupSteps //original project
import io.cucumber.java.Before
import io.cucumber.java.PendingException
import io.cucumber.java.Scenario
import io.cucumber.java8.En
import org.springframework.beans.factory.annotation.Autowired
class OtherFeatureSteps @Autowired constructor(private var setupSteps: SetupSteps) : En {
private lateinit var scenario: Scenario
@Before
fun initialise(scenario: Scenario) {
this.scenario = scenario
}
init {
Given("Some other state") {
// code here
}
}
}
在尝试使用旧项目运行Cucumber测试时,一切正常。但是当我尝试使用新项目运行时,我得到了以下错误:
Apr 08, 2020 11:36:07 AM io.cucumber.core.runtime.Runtime run
SEVERE: Exception while executing pickle
java.util.concurrent.ExecutionException: io.cucumber.core.backend.CucumberBackendException: Error creating bean with name 'com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps.<init>()
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:110)
at io.cucumber.core.cli.Main.run(Main.java:63)
at io.cucumber.core.cli.Main.main(Main.java:27)
Caused by: io.cucumber.core.backend.CucumberBackendException: Error creating bean with name 'com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps.<init>()
at io.cucumber.spring.SpringFactory.getInstance(SpringFactory.java:213)
at io.cucumber.java8.Java8Backend.buildWorld(Java8Backend.java:62)
at io.cucumber.core.runner.Runner.buildBackendWorlds(Runner.java:165)
at io.cucumber.core.runner.Runner.runPickle(Runner.java:61)
at io.cucumber.core.runtime.Runtime.lambda$null$2(Runtime.java:102)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:258)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at io.cucumber.core.runtime.Runtime.lambda$run$3(Runtime.java:102)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.stream.SliceOps$1$1.accept(SliceOps.java:204)
at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:499)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:486)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:103)
... 2 more
我对使用Spring的经验不多,原始项目是由其他人设置的。有谁能看出出了什么问题吗?
我尝试在新的步骤文件顶部添加了@ContextConfiguration(classes = [AppConfiguration::class])
,这让我进展了一些,但出现了不同的错误信息:
Apr 08, 2020 11:46:20 AM io.cucumber.core.runtime.Runtime run
SEVERE: Exception while executing pickle
java.util.concurrent.ExecutionException: io.cucumber.core.backend.CucumberBackendException: Error creating bean with name 'com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.cucumberproject.hooks.FeatureSteps' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:110)
at io.cucumber.core.cli.Main.run(Main.java:63)
at io.cucumber.core.cli.Main.main(Main.java:27)
但是说实
英文:
I have a project with Cucumber for java set up, (actually using Kotlin but this is just using java under the hood).
It uses spring for DI and a setup that works fine with the following configuration:
package com.cucumberproject.projectA.hooks
import com.cucumberproject.projectA.profile.ProfileManager
import com.cucumberproject.projectA.profile.EnvironmentProfile
import org.springframework.context.annotation.Bean
class AppConfiguration {
@Bean
fun profileManager(): EnvironmentProfile {
return ProfileManager().getEnvProfile(
"clientId",
"clientSecret",
TokenUrl,
AuthorisationUrl);
}
}
package com.cucumberproject.projectA.hooks
import io.cucumber.java8.En
import org.springframework.test.context.ContextConfiguration
@ContextConfiguration(classes = [AppConfiguration::class])
class SetupSteps : En {
}
import com.cucumberproject.projectA.hooks.*
import com.cucumberproject.projectA.profile.EnvironmentProfile
import io.cucumber.java.PendingException
import io.cucumber.java.Scenario
import io.cucumber.java8.En
class FeatureSteps @Autowired constructor(private var profile: EnvironmentProfile) : En {
private lateinit var scenario: Scenario
@Before
fun initialise(scenario: Scenario) {
this.scenario = scenario
}
init {
Given("A certain state") {
// code in here that works
}
I am trying to create a new project with the same setup. It has access to the same AppConfiguration file, EnvironmentProfile file and SetupSteps file as they are pulled in as a dependency.
package com.cucumberproject2.projectB.stepdefs
import com.cucumberproject.hooks.AppConfiguration //original project
import com.cucumberproject.hooks.SetupSteps //original project
import com.cucumberproject.stepdefs.ProgramSetupSteps //original project
import io.cucumber.java.Before
import io.cucumber.java.PendingException
import io.cucumber.java.Scenario
import io.cucumber.java8.En
import org.springframework.beans.factory.annotation.Autowired
class OtherFeatureSteps @Autowired constructor(private var setupSteps: SetupSteps) : En {
private lateinit var scenario: Scenario
@Before
fun initialise(scenario: Scenario) {
this.scenario = scenario
}
init {
Given("Some other state") {
// code here
}
}
}
When trying to run the cucumber tests with the old project, everything works fine. When I try with the new project I get this error:
Apr 08, 2020 11:36:07 AM io.cucumber.core.runtime.Runtime run
SEVERE: Exception while executing pickle
java.util.concurrent.ExecutionException: io.cucumber.core.backend.CucumberBackendException: Error creating bean with name 'com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps.<init>()
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:110)
at io.cucumber.core.cli.Main.run(Main.java:63)
at io.cucumber.core.cli.Main.main(Main.java:27)
Caused by: io.cucumber.core.backend.CucumberBackendException: Error creating bean with name 'com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps.<init>()
at io.cucumber.spring.SpringFactory.getInstance(SpringFactory.java:213)
at io.cucumber.java8.Java8Backend.buildWorld(Java8Backend.java:62)
at io.cucumber.core.runner.Runner.buildBackendWorlds(Runner.java:165)
at io.cucumber.core.runner.Runner.runPickle(Runner.java:61)
at io.cucumber.core.runtime.Runtime.lambda$null$2(Runtime.java:102)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:258)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at io.cucumber.core.runtime.Runtime.lambda$run$3(Runtime.java:102)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.stream.SliceOps$1$1.accept(SliceOps.java:204)
at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:499)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:486)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:103)
... 2 more
I haven't got much experience with using Spring and the original project was setup by someone else. Can anyone see what's going wrong?
I've tried adding the @ContextConfiguration(classes = [AppConfiguration::class])
to the top of the new steps file, which gets me a bit further and a different error message:
Apr 08, 2020 11:46:20 AM io.cucumber.core.runtime.Runtime run
SEVERE: Exception while executing pickle
java.util.concurrent.ExecutionException: io.cucumber.core.backend.CucumberBackendException: Error creating bean with name 'com.cucumberproject2.projectB.stepdefs.OtherFeatureSteps': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.cucumberproject.hooks.FeatureSteps' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:110)
at io.cucumber.core.cli.Main.run(Main.java:63)
at io.cucumber.core.cli.Main.main(Main.java:27)
But honestly, I have no idea if this is the correct thing to do. Any help with this would be much appreciated!
专注分享java语言的经验与见解,让所有开发者获益!
评论