简体   繁体   English

在 Springboot 中运行 Cucumber,在可执行文件 JAR 中运行 Maven

[英]Running Cucumber in Springboot with Maven in executable JAR

Hello fellow engineers!各位工程师好!

I have run into a problem when trying to create a FAT jar to execute the Cucumber tests.我在尝试创建 FAT jar 以执行 Cucumber 测试时遇到问题。 Initially, I have followed the guide to set up the tests from Baeldung .最初,我按照指南从Baeldung设置测试。 The tests are working fine when executed during the Maven test phase.在 Maven 测试阶段执行时,测试工作正常。 It is also working as expected when running the mvn exec:java command with the parameters.当使用参数运行 mvn exec:java 命令时,它也按预期工作。

However, when I have a FAT jar created and I try to execute the tests I am faced with the error但是,当我创建了一个 FAT jar 并尝试执行测试时,我遇到了错误

java.util.concurrent.ExecutionException: io.cucumber.core.backend.CucumberBackendException: Please annotate a glue class with some context configuration.

For example:

   @CucumberContextConfiguration
   @SpringBootTest(classes = TestConfig.class)
   public class CucumberSpringConfiguration { }
Or:

   @CucumberContextConfiguration
   @ContextConfiguration( ... )

Here is the explanation of my project, which is basically almost exactly as the test project at Baeldung.这是我的项目的解释,基本上和Baeldung的测试项目几乎一模一样。

Project Structure项目结构

RunCucumberTest.java RunCucumberTest.java

package com.ing.testsuite;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Configuration;
import io.cucumber.*;


@RunWith(Cucumber.class)
@CucumberOptions(features="src/test/resources", glue="com.ing.testsuite", plugin = {"pretty","html:target/cucumber.html"})
class RunCucumberTest {

    public static void main(String[] args) throws Throwable {
        String[] arguments = {"classpath:dummy.feature", "classpath:com.ing.testsuite"};
        io.cucumber.core.cli.Main.main(arguments);
    }
}

CucumberSpringConfiguration.java CucumberSpringConfiguration.java

package com.ing.testsuite;

import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;

@CucumberContextConfiguration
@SpringBootTest(classes = RunCucumberTest.class)
public class CucumberSpringConfiguration{
}

StepDefinitions.java步骤定义.java

package com.ing.testsuite;

import static org.junit.jupiter.api.Assertions.assertEquals;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;

public class StepDefinitions extends CucumberSpringConfiguration{

    private Integer noOfCucumbers;
    private Integer noOfCucumberEaten;
    private Integer noOfRemainingCucumber;

    @Given("There are {int} cucumbers")
    public void cucumberTest_nrOne(Integer noOfCucumber) throws Throwable{
        noOfCucumbers = noOfCucumber;
    }

    @When("I eat {int} cucumbers")
    public void cucumberTest_nrTwo(Integer noOfCucumberEaten) throws Throwable{
        noOfCucumbers = noOfCucumbers - noOfCucumberEaten;
    }

    @Then("I should have {int} cucumbers")
    public void cucumberTest_nrThree(Integer noOfRemainingCucumber) throws Throwable{
        assertEquals(noOfCucumbers,noOfRemainingCucumber);
    }


}

dummy.feature虚拟特征

Feature: This is dummy test scenario
  Scenario Outline: Eating
  Given There are <start> cucumbers
  When I eat <eat> cucumbers
  Then I should have <left> cucumbers

  Examples:
  | start | eat | left |
  |  12   |  5  |  7   |
  |  20   |  5  |  15  |
  |  30   |  5  |  25  |

assembly.xml组装.xml

<assembly
    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
    <id>fat-tests</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>test</scope>
        </dependencySet>
    </dependencySets>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/test-classes</directory>
            <outputDirectory></outputDirectory>
            <includes>
                <include>**/*.*</include>
               </includes>
            <useDefaultExcludes>true</useDefaultExcludes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/test-classes</directory>
            <outputDirectory></outputDirectory>
            <includes>
                <include>*.feature</include>
            </includes>
            <useDefaultExcludes>true</useDefaultExcludes>
        </fileSet>
    </fileSets>
</assembly>

Some of the resources I have already tried to follow我已经尝试关注的一些资源

I would really appreciate if someone could help me out.如果有人能帮助我,我将不胜感激。

I just had the same issue but with Gradle. I was trying to run Cucumber tests from a jar file and was getting an identical error.我只是遇到了同样的问题,但问题是 Gradle。我试图从 jar 文件运行 Cucumber 测试,但遇到了相同的错误。

Short answer简答

In build.gradle I've added next code:在 build.gradle 中,我添加了下一个代码:

 shadowJar {
     ....
     transform(AppendingTransformer) {
        resource = 'META-INF/services/io.cucumber.core.backend.BackendProviderService'
     }
 }

Analogy in Maven would be something like: Maven 中的类比是这样的:

<transformers>
    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
        <resource>META-INF/services/io.cucumber.core.backend.BackendProviderService</resource>
    </transformer>
</transformers>

A little longer explanation稍微长一点的解释

After debugging for some time (thanks Yulia) we found out how cucumber looks for Glue (Glue classes are all the classes that cucumber requires for run - stepdef classes, contextconfigurator, ...).调试了一段时间后(感谢 Yulia),我们发现了 cucumber 是如何寻找 Glue 的(Glue 类是 cucumber 运行所需的所有类——stepdef 类、contextconfigurator 等)。

It looks for those classes with BackendService(es), instances of which are getting created at some point.它查找那些具有 BackendService(es) 的类,这些类的实例在某个时候被创建。

In the successful case there were 2 services instantiated:在成功案例中,实例化了 2 个服务:

  • io.cucumber.java.JavaBackendProviderService io.cucumber.java.JavaBackendProviderService
  • io.cucumber.spring.SpringBackendProviderService io.cucumber.spring.SpringBackendProviderService

In the failed case (found out by debugging run from jar) there was only one:在失败的情况下(通过从 jar 运行调试发现)只有一个:

  • io.cucumber.java.JavaBackendProviderService io.cucumber.java.JavaBackendProviderService

Turned out that which BackendService to instantiate exactly it finds in this file - META-INF/services/io.cucumber.core.backend.BackendProviderService.原来,它在这个文件中找到了要实例化的 BackendService - META-INF/services/io.cucumber.core.backend.BackendProviderService。

Unpacking the jar showed that there is indeed only one service listed - Java.解包 jar 显示确实只列出了一项服务 - Java。

No Spring backend service instantiated means it couldn't find the Spring components.没有 Spring 后端服务实例化意味着它找不到 Spring 组件。

These files are coming from the cucumber libs:这些文件来自 cucumber 库:

  • Java from cucumber-java Java 来自黄瓜-java
  • Spring from cucumber-spring Spring 来自 cucumber-spring

So it boils down to our packaging process not being able to merge these 2 files together, it was picking the first one and not applying the second one.所以归结为我们的打包过程无法将这两个文件合并在一起,它选择了第一个文件而不应用第二个文件。

When running from the IDE they seem to be merged fine.从 IDE 运行时,它们似乎合并得很好。

So adding the code above says packaging task (shadowJar in my case) how to deal with this file, adds a rule to merge all the files with this name it will find (in META-INF of course).所以添加上面的代码说打包任务(在我的例子中是 shadowJar)如何处理这个文件,添加一个规则来合并所有它会找到的这个名字的文件(当然在 META-INF 中)。

I hope you have already solved your issue, and if not - I hope my experience will help with your problem as well.我希望你已经解决了你的问题,如果没有 - 我希望我的经验也能帮助你解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM