Spring 使用 Cucumber 时在嵌入式 Cassandra 之前启动加载,我该如何解决这个问题?
Spring Boot Loads Before Embedded Cassandra When Using Cucumber, How Can I Fix This?
我在使用 spring-cassandra-unit、spring-boot 和 spring-cucumber 时遇到了一些问题。下面的配置适用于单元测试,但是一旦我将 spring-cucumber 添加到组合中并尝试一些集成测试,它似乎完全忽略了我的 MyCustomOrderedTestExecutionListener 并在 cassandra 之前加载 spring 引导,给我一个 "NoHostFoundException"。
我真的可以使用有关如何确保首先加载嵌入式 cassandra 的建议。非常感谢任何帮助。
以下设置:
@ActiveProfile("INTEGRATION_TEST")
@SpringBootTest
@EmbeddedCassandra(configuration = "cassandra.yaml")
@TestExecutionListeners(
listeners = MyCustomOrderedTestExecutionListener.class,
mergeMode = MERGE_WITH_DEFAULTS)
@CassandraDataSet(value = "cql/dataset1.cql", keyspace = "mykeyspace")
public class TestStepDef{
//omitted for brevity
}
我的自定义命令测试执行侦听器:
public class MyCustomOrderedTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void afterTestMethod(TestContext testContext) throws Exception {
//omitted for brevity
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
Cucumber 测试运行程序:
@RunWith(Cucumber.class)
@CucumberOptions(features="resources/features", glue="resources/glue")
public class TestRunner {}
编辑:
查看 cucumber spring 的 spring 工厂,甚至在执行 beforeTestClass 之前加载应用程序上下文(beforeTestClass 由 notifyContextManagerAboutTestClassStarted 执行):
public void start() {
if (this.stepClassWithSpringContext != null) {
this.testContextManager = new CucumberTestContextManager(this.stepClassWithSpringContext);
} else if (this.beanFactory == null) {
this.beanFactory = this.createFallbackContext();
}
this.notifyContextManagerAboutTestClassStarted();
if (this.beanFactory == null || this.isNewContextCreated()) {
this.beanFactory = this.testContextManager.getBeanFactory();
Iterator var1 = this.stepClasses.iterator();
while(var1.hasNext()) {
Class<?> stepClass = (Class)var1.next();
this.registerStepClassBeanDefinition(this.beanFactory, stepClass);
}
}
GlueCodeContext.INSTANCE.start();
}
再深入一点,我们可以看到应用上下文已加载到此处:
class CucumberTestContextManager extends TestContextManager {
public CucumberTestContextManager(Class<?> testClass) {
super(testClass);
this.registerGlueCodeScope(this.getContext());
}
private ConfigurableApplicationContext getContext() {
return (ConfigurableApplicationContext)this.getTestContext().getApplicationContext();
}
...
}
关于如何解决这个问题有什么建议吗?
目前 Cucumber 仅调用 TestContextManager.beforeClass
和 TestContextManager.afterClass
。然而,这发生在每个场景之前,因此覆盖 TestExecutionListener.afterTestClass
应该可以解决问题。
我是这样做的:
集成配置:
class IntegrationConfiguration {
// your cassandra startup
}
组件测试规范:
@ContextConfiguration(classes = Application.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@Import(IntegrationConfiguration.class)
abstract class ComponentTestSpecification {
// reusable integration-test methods here
}
测试(groovy,应该可以转换为 jUnit / 其他):
class AccessControllerSpec extends ComponentTestSpecification {
// test methods
}
您可以通过 https://github.com/nosan/embedded-cassandra 项目
完成此操作
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import com.github.nosan.embedded.cassandra.test.spring.EmbeddedCassandra;
@SpringBootTest
@ActiveProfiles("INTEGRATION_TEST")
@EmbeddedCassandra(configurationFile = "cassandra.yaml", scripts = "cql/dataset1.cql")
public class TestStepDef {
}
@EmbeddedCassandra
由 org.springframework.test.context.ContextCustomizer
处理,因此启动时不会有任何问题。
我在使用 spring-cassandra-unit、spring-boot 和 spring-cucumber 时遇到了一些问题。下面的配置适用于单元测试,但是一旦我将 spring-cucumber 添加到组合中并尝试一些集成测试,它似乎完全忽略了我的 MyCustomOrderedTestExecutionListener 并在 cassandra 之前加载 spring 引导,给我一个 "NoHostFoundException"。
我真的可以使用有关如何确保首先加载嵌入式 cassandra 的建议。非常感谢任何帮助。
以下设置:
@ActiveProfile("INTEGRATION_TEST")
@SpringBootTest
@EmbeddedCassandra(configuration = "cassandra.yaml")
@TestExecutionListeners(
listeners = MyCustomOrderedTestExecutionListener.class,
mergeMode = MERGE_WITH_DEFAULTS)
@CassandraDataSet(value = "cql/dataset1.cql", keyspace = "mykeyspace")
public class TestStepDef{
//omitted for brevity
}
我的自定义命令测试执行侦听器:
public class MyCustomOrderedTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void afterTestMethod(TestContext testContext) throws Exception {
//omitted for brevity
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
Cucumber 测试运行程序:
@RunWith(Cucumber.class)
@CucumberOptions(features="resources/features", glue="resources/glue")
public class TestRunner {}
编辑:
查看 cucumber spring 的 spring 工厂,甚至在执行 beforeTestClass 之前加载应用程序上下文(beforeTestClass 由 notifyContextManagerAboutTestClassStarted 执行):
public void start() {
if (this.stepClassWithSpringContext != null) {
this.testContextManager = new CucumberTestContextManager(this.stepClassWithSpringContext);
} else if (this.beanFactory == null) {
this.beanFactory = this.createFallbackContext();
}
this.notifyContextManagerAboutTestClassStarted();
if (this.beanFactory == null || this.isNewContextCreated()) {
this.beanFactory = this.testContextManager.getBeanFactory();
Iterator var1 = this.stepClasses.iterator();
while(var1.hasNext()) {
Class<?> stepClass = (Class)var1.next();
this.registerStepClassBeanDefinition(this.beanFactory, stepClass);
}
}
GlueCodeContext.INSTANCE.start();
}
再深入一点,我们可以看到应用上下文已加载到此处:
class CucumberTestContextManager extends TestContextManager {
public CucumberTestContextManager(Class<?> testClass) {
super(testClass);
this.registerGlueCodeScope(this.getContext());
}
private ConfigurableApplicationContext getContext() {
return (ConfigurableApplicationContext)this.getTestContext().getApplicationContext();
}
...
}
关于如何解决这个问题有什么建议吗?
目前 Cucumber 仅调用 TestContextManager.beforeClass
和 TestContextManager.afterClass
。然而,这发生在每个场景之前,因此覆盖 TestExecutionListener.afterTestClass
应该可以解决问题。
我是这样做的:
集成配置:
class IntegrationConfiguration {
// your cassandra startup
}
组件测试规范:
@ContextConfiguration(classes = Application.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@Import(IntegrationConfiguration.class)
abstract class ComponentTestSpecification {
// reusable integration-test methods here
}
测试(groovy,应该可以转换为 jUnit / 其他):
class AccessControllerSpec extends ComponentTestSpecification {
// test methods
}
您可以通过 https://github.com/nosan/embedded-cassandra 项目
完成此操作import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import com.github.nosan.embedded.cassandra.test.spring.EmbeddedCassandra;
@SpringBootTest
@ActiveProfiles("INTEGRATION_TEST")
@EmbeddedCassandra(configurationFile = "cassandra.yaml", scripts = "cql/dataset1.cql")
public class TestStepDef {
}
@EmbeddedCassandra
由 org.springframework.test.context.ContextCustomizer
处理,因此启动时不会有任何问题。