首页 > 解决方案 > Cucumber 5.0.0 和 springboot 多个场景在一个特性文件中

问题描述

我对 springboot 的依赖:

    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java8</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-spring</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>



Feature: Bag Functionality

  Scenario: Putting one thing in the bag
    Given the bag is empty
    When I put 1 potato in the bag
    Then the bag should contain only 1 potato

  Scenario: Putting few things in the bag
    Given the bag is empty
    When I put 1 potato in the bag
    And I put 2 cucumber in the bag
    Then the bag should contain 1 potato

当我运行此功能文件时出现异常

05:08:16.249 [main] DEBUG org.springframework.context.support.GenericApplicationContext - Refreshing org.springframework.context.support.GenericApplicationContext@6f03482
Feb 28, 2020 5:08:16 AM io.cucumber.core.runtime.Runtime run
SEVERE: Exception while executing pickle
java.util.concurrent.ExecutionException: java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
    at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
    at io.cucumber.core.runtime.Runtime.run(Runtime.java:108)
    at io.cucumber.core.cli.Main.run(Main.java:73)
    at cucumber.api.cli.Main.run(Main.java:28)
    at cucumber.api.cli.Main.main(Main.java:15)
Caused by: java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
    at org.springframework.context.support.GenericApplicationContext.refreshBeanFactory(GenericApplicationContext.java:266)
    at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:637)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:522)
    at io.cucumber.spring.TestContextAdaptor$FallbackApplicationContextAdaptor.start(TestContextAdaptor.java:127)
    at io.cucumber.spring.SpringFactory.start(SpringFactory.java:165)
    at io.cucumber.core.runner.Runner.buildBackendWorlds(Runner.java:163)
    at io.cucumber.core.runner.Runner.runPickle(Runner.java:61)
    at io.cucumber.core.runtime.Runtime.lambda$null$2(Runtime.java:100)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:243)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
    at io.cucumber.core.runtime.Runtime.lambda$run$3(Runtime.java:100)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:199)
    at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1631)
    at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
    at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
    at io.cucumber.core.runtime.Runtime.run(Runtime.java:101)
    ... 3 more

Exception in thread "main" io.cucumber.core.exception.CucumberException: java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
    at io.cucumber.core.runtime.Runtime.run(Runtime.java:118)
    at io.cucumber.core.cli.Main.run(Main.java:73)
    at cucumber.api.cli.Main.run(Main.java:28)
    at cucumber.api.cli.Main.main(Main.java:15)
Caused by: java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
    at org.springframework.context.support.GenericApplicationContext.refreshBeanFactory(GenericApplicationContext.java:266)
    at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:637)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:522)
    at io.cucumber.spring.TestContextAdaptor$FallbackApplicationContextAdaptor.start(TestContextAdaptor.java:127)
    at io.cucumber.spring.SpringFactory.start(SpringFactory.java:165)
    at io.cucumber.core.runner.Runner.buildBackendWorlds(Runner.java:163)
    at io.cucumber.core.runner.Runner.runPickle(Runner.java:61)
    at io.cucumber.core.runtime.Runtime.lambda$null$2(Runtime.java:100)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:243)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
    at io.cucumber.core.runtime.Runtime.lambda$run$3(Runtime.java:100)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:199)
    at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1631)
    at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
    at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
    at io.cucumber.core.runtime.Runtime.run(Runtime.java:101)
    ... 3 more
05:08:16.257 [SpringContextShutdownHook] DEBUG org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@6f03482, started on Fri Feb 28 05:08:16 CET 2020

Process finished with exit code 1

它成功运行一个场景并在第二个场景中崩溃。

如果我将黄瓜的版本更改为 4.8.1,这两种情况都可以运行。使用spring boot不可能从黄瓜5中的一个功能文件运行多个场景吗?

标签: cucumber

解决方案


看起来你遇到了 Cucumber 的错误。Cucumber 在您的步骤定义中找不到上下文配置,因此它回退到GenericApplicationContext无法在场景之间刷新的情况。

尝试将上下文配置添加到您的步骤定义中。例如:

├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── com
    │           └── example
    │               └── Application.java
    └── test
        ├── java
        │   └── com
        │       └── example
        │           ├── RunCucumberTest.java
        │           └── StepDefinitions.java
        └── resources
            └── com
                └── example
                    └── example.feature

package com.example;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
}
package com.example;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(plugin = {"pretty"})
public class RunCucumberTest {
}
package com.example;

import io.cucumber.java.en.Given;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.annotation.DirtiesContext;

import static org.junit.Assert.assertNotNull;

@SpringBootTest
public class StepDefinitions {
    @Autowired
    private ApplicationContext applicationContext;

    @Given("an application context")
    public void anApplicationContext() {
        assertNotNull(applicationContext);
    }
}

因为StepDefinitions使用上下文配置 ( @SpringBootTest) 注释,所以黄瓜会将其传递给 Springs TestContextManager。这将创建应用程序上下文并确保场景执行类似于使用SpringRunner/SpringExtension.

您还可以在此处使用其他上下文配置。例如:

package com.example;

import io.cucumber.java.en.Given;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;

import static org.junit.Assert.assertNotNull;

@ContextConfiguration("classpath:cucumber.xml")
public class StepDefinitions {
    @Autowired
    private ApplicationContext applicationContext;

    @Given("an application context")
    public void anApplicationContext() {
        assertNotNull(applicationContext);
    }
}

推荐阅读