Spring Cucumber ActiveProfiles 注释不适用于 CucumberContext
Spring Cucumber ActiveProfiles annotation not working with CucumberContext
我正在做一个项目,我们有一个组件包含:
- 核心
- 连接到外部系统 1
- 连接到外部系统 2
连接器相互排斥(如果连接器 1 处于活动状态,则连接器 2 始终处于非活动状态,反之亦然)。核心和单个连接器在 ApplicationContext 启动时自动连接。实例化哪个连接器基于 spring 应用程序属性中的值。
我们正在使用 spring-cucumber (v6.2.2) 编写集成测试。对于每个外部系统,我想 运行 一组黄瓜测试。我已经使用黄瓜场景上的注释创建了 2 个测试集,这使我能够将 connector1 和 connector2 的测试分开。
我遇到的问题是,我需要两个测试集都 运行 具有不同的 spring 配置文件,因此我可以使用不同的配置。我找不到如何执行此操作。
当前实施(使用单个配置文件):
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
CucumberConnector1IT.java
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
features = { "classpath:feature/" },
glue = { "omitted.for.company.rules.cucumber.step" },
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "@Connector1 and not @ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector1IT {
}
CucumberConnector2IT.java
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
features = { "classpath:feature/" },
glue = { "omitted.for.company.rules.cucumber.step" },
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "@Connector2 and not @ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector2IT {
}
StepInitializer.java
package omitted.for.company.rules.steps;
import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest
@ActiveProfiles("test") // I can only get this to work if the @ActiveProfiles and @CucumberContextConfiguration annotations are on the same class
@CucumberContextConfiguration
public class StepInitializer {
// mock some beans to use in cucumber test
@MockBean
private EventProducer eventProducer;
@MockBean
private RestInterface restInterface;
@Before
public void setup() {
}
}
到目前为止一切正常。但我现在需要的是将 @ActiveProfiles()
注释放在与 @CucumberContextConfiguration
不同的 class 上。如果我能做到这一点,那么我就可以用所需的配置文件注释正确的步骤 classes。
问题是我不太了解 spring 注释,不知道哪些可以移动,哪些不能。我发现这个例子 正是 我正在尝试做的事情 (spring-cucumber-profiles repo, notice the location of the @ActiveProfiles
annotation here) . Unfortunately, it uses an older version of cucumber-spring
(v5.6.0). That version doesn't yet have the @CucumberContextConfiguration
annotation and does some magic with the spring context according to the documentation (Release notes of cucumber-spring)。我尝试检查示例存储库并将其升级到 v6.2.2,但无法使用新版本。
如果有人发现我在自己的示例中做错了什么,或者有可能使示例回购与 cucumber-spring
的 6.2.2 版一起使用,我们将不胜感激。
提前致谢! :)
我已经通过稍微分离包并为两个测试集创建单独的 StepInitializer
classes 解决了这个问题。
当前设置:
测试运行器:
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
features = { "classpath:feature/" },
extraGlue = { "omitted.for.company.rules.cucumber.step.common" }, // used extraGlue instead of glue
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "@Connector1 and not @ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector1IT {
}
上下文配置:
package omitted.for.company.rules.steps;
import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest
@ActiveProfiles({ "test", "test-connector1" })
@CucumberContextConfiguration
public class Connector1StepInitializer {
// mock some beans to use in cucumber test
@MockBean
private EventProducer eventProducer;
@MockBean
private RestInterface restInterface;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private Environment environment;
@Before
public void setup() {
assertThat(applicationContext).isNotNull();
assertThat(environment.getActiveProfiles()).containsOnly("test","test-connector1");
}
}
两个 connectors/test 运行器都有自己的运行器 class 和它们自己的 ContextConfiguration class。
非常重要的是,包含@CucumberContextConfiguration
注释的classes不在共享胶水包中(如extraGlue
属性中提供的@CucumberOptions
注解).
包结构如下所示:
├───common
│ └───step // Contains shared steps. This path should be in the 'extraGlue' field of the runner classes
├───connector1
│ │ CucumberConnector1IT.java // Runner 1
│ └───step
│ Connector1Steps.java // Specific steps
│ Connector1StepInitializer.java // has @ActiveProfiles and @CucumberContextConfiguration annotations, use to mock beans
└───connector2
│ CucumberConnector1IT.java // Runner 2
└───step
Connector2Steps.java // Specific steps
Connector2StepInitializer.java // has @ActiveProfiles and @CucumberContextConfiguration annotations, use to mock beans
这样我仍然可以使用不同的 spring 配置文件 :)。
我正在做一个项目,我们有一个组件包含:
- 核心
- 连接到外部系统 1
- 连接到外部系统 2
连接器相互排斥(如果连接器 1 处于活动状态,则连接器 2 始终处于非活动状态,反之亦然)。核心和单个连接器在 ApplicationContext 启动时自动连接。实例化哪个连接器基于 spring 应用程序属性中的值。
我们正在使用 spring-cucumber (v6.2.2) 编写集成测试。对于每个外部系统,我想 运行 一组黄瓜测试。我已经使用黄瓜场景上的注释创建了 2 个测试集,这使我能够将 connector1 和 connector2 的测试分开。
我遇到的问题是,我需要两个测试集都 运行 具有不同的 spring 配置文件,因此我可以使用不同的配置。我找不到如何执行此操作。
当前实施(使用单个配置文件):
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
CucumberConnector1IT.java
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
features = { "classpath:feature/" },
glue = { "omitted.for.company.rules.cucumber.step" },
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "@Connector1 and not @ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector1IT {
}
CucumberConnector2IT.java
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
features = { "classpath:feature/" },
glue = { "omitted.for.company.rules.cucumber.step" },
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "@Connector2 and not @ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector2IT {
}
StepInitializer.java
package omitted.for.company.rules.steps;
import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest
@ActiveProfiles("test") // I can only get this to work if the @ActiveProfiles and @CucumberContextConfiguration annotations are on the same class
@CucumberContextConfiguration
public class StepInitializer {
// mock some beans to use in cucumber test
@MockBean
private EventProducer eventProducer;
@MockBean
private RestInterface restInterface;
@Before
public void setup() {
}
}
到目前为止一切正常。但我现在需要的是将 @ActiveProfiles()
注释放在与 @CucumberContextConfiguration
不同的 class 上。如果我能做到这一点,那么我就可以用所需的配置文件注释正确的步骤 classes。
问题是我不太了解 spring 注释,不知道哪些可以移动,哪些不能。我发现这个例子 正是 我正在尝试做的事情 (spring-cucumber-profiles repo, notice the location of the @ActiveProfiles
annotation here) . Unfortunately, it uses an older version of cucumber-spring
(v5.6.0). That version doesn't yet have the @CucumberContextConfiguration
annotation and does some magic with the spring context according to the documentation (Release notes of cucumber-spring)。我尝试检查示例存储库并将其升级到 v6.2.2,但无法使用新版本。
如果有人发现我在自己的示例中做错了什么,或者有可能使示例回购与 cucumber-spring
的 6.2.2 版一起使用,我们将不胜感激。
提前致谢! :)
我已经通过稍微分离包并为两个测试集创建单独的 StepInitializer
classes 解决了这个问题。
当前设置:
测试运行器:
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
features = { "classpath:feature/" },
extraGlue = { "omitted.for.company.rules.cucumber.step.common" }, // used extraGlue instead of glue
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "@Connector1 and not @ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector1IT {
}
上下文配置:
package omitted.for.company.rules.steps;
import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest
@ActiveProfiles({ "test", "test-connector1" })
@CucumberContextConfiguration
public class Connector1StepInitializer {
// mock some beans to use in cucumber test
@MockBean
private EventProducer eventProducer;
@MockBean
private RestInterface restInterface;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private Environment environment;
@Before
public void setup() {
assertThat(applicationContext).isNotNull();
assertThat(environment.getActiveProfiles()).containsOnly("test","test-connector1");
}
}
两个 connectors/test 运行器都有自己的运行器 class 和它们自己的 ContextConfiguration class。
非常重要的是,包含@CucumberContextConfiguration
注释的classes不在共享胶水包中(如extraGlue
属性中提供的@CucumberOptions
注解).
包结构如下所示:
├───common
│ └───step // Contains shared steps. This path should be in the 'extraGlue' field of the runner classes
├───connector1
│ │ CucumberConnector1IT.java // Runner 1
│ └───step
│ Connector1Steps.java // Specific steps
│ Connector1StepInitializer.java // has @ActiveProfiles and @CucumberContextConfiguration annotations, use to mock beans
└───connector2
│ CucumberConnector1IT.java // Runner 2
└───step
Connector2Steps.java // Specific steps
Connector2StepInitializer.java // has @ActiveProfiles and @CucumberContextConfiguration annotations, use to mock beans
这样我仍然可以使用不同的 spring 配置文件 :)。