[英]Running Cucumber in Springboot with Maven in executable JAR
各位工程师好!
我在尝试创建 FAT jar 以执行 Cucumber 测试时遇到问题。 最初,我按照指南从Baeldung设置测试。 在 Maven 测试阶段执行时,测试工作正常。 当使用参数运行 mvn exec:java 命令时,它也按预期工作。
但是,当我创建了一个 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( ... )
这是我的项目的解释,基本上和Baeldung的测试项目几乎一模一样。
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);
}
}
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{
}
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);
}
}
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
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>
如果有人能帮助我,我将不胜感激。
我只是遇到了同样的问题,但问题是 Gradle。我试图从 jar 文件运行 Cucumber 测试,但遇到了相同的错误。
在 build.gradle 中,我添加了下一个代码:
shadowJar {
....
transform(AppendingTransformer) {
resource = 'META-INF/services/io.cucumber.core.backend.BackendProviderService'
}
}
Maven 中的类比是这样的:
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/services/io.cucumber.core.backend.BackendProviderService</resource>
</transformer>
</transformers>
调试了一段时间后(感谢 Yulia),我们发现了 cucumber 是如何寻找 Glue 的(Glue 类是 cucumber 运行所需的所有类——stepdef 类、contextconfigurator 等)。
它查找那些具有 BackendService(es) 的类,这些类的实例在某个时候被创建。
在成功案例中,实例化了 2 个服务:
在失败的情况下(通过从 jar 运行调试发现)只有一个:
原来,它在这个文件中找到了要实例化的 BackendService - META-INF/services/io.cucumber.core.backend.BackendProviderService。
解包 jar 显示确实只列出了一项服务 - Java。
没有 Spring 后端服务实例化意味着它找不到 Spring 组件。
这些文件来自 cucumber 库:
所以归结为我们的打包过程无法将这两个文件合并在一起,它选择了第一个文件而不应用第二个文件。
从 IDE 运行时,它们似乎合并得很好。
所以添加上面的代码说打包任务(在我的例子中是 shadowJar)如何处理这个文件,添加一个规则来合并所有它会找到的这个名字的文件(当然在 META-INF 中)。
我希望你已经解决了你的问题,如果没有 - 我希望我的经验也能帮助你解决问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.