Spring Cucumber ActiveProfiles注释不适用于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

@H_502_26@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

@H_502_26@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/" },tags = "@Connector2 and not @ignore" // tags make sure only applicable tests are run ) public class CucumberConnector2IT { }

StepInitializer.java

@H_502_26@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不同的类上。如果可以,则可以使用所需的配置文件注释正确的步骤类。

问题是,我对弹簧注释的理解不够充分,无法知道可以移动哪些注释和不能移动哪些注释。我发现了这个完全我正在尝试做的示例(spring-cucumber-profiles reponotice the location of the @ActiveProfiles annotation here)。不幸的是,它使用了cucumber-springv5.6.0)的旧版本。该版本尚没有@CucumberContextConfiguration批注,并且根据文档(Release notes of cucumber-spring)对spring上下文进行了一些魔术处理。我尝试签出示例存储库并将其升级到v6.2.2,但无法使其与新版本一起使用。

如果有人发现我自己的示例中做错了什么,或者有可能使示例存储库与cucumber-spring的6.2.2版本一起使用,将不胜感激。

提前谢谢! :)

解决方法

我已经解决了这个问题,方法是将包分开一点,并为两个测试集创建单独的StepInitializer类。

当前设置:

测试跑步者:

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");
    }
}

连接器/测试运行器都有自己的运行器类和自己的ContextConfiguration类。

非常重要的一点是,包含@CucumberContextConfiguration批注的类不在共享的粘合包中(如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

这样,我仍然可以使用不同的弹簧轮廓:)。