新しいアプリを作成していて、キュウリとSpring Boot1.4を使用してBDDを実行しようとしています。動作するコードは次のとおりです。
@SpringBootApplication
public class Application {
@Bean
MyService myService() {
return new MyService();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
public class MyService {}
テストコードは次のとおりです。
@RunWith(Cucumber.class)
public class RunFeatures {}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
public class MyStepDef {
@Autowired
MyService myService;
@Given("^Some initial condition$")
public void appIsStarted() throws Throwable {
if (service == null) throw new Exception("Dependency not injected!");
System.out.println("App started");
}
@Then("^Nothing happens$")
public void thereShouldBeNoException() throws Throwable {
System.out.println("Test passed");
}
}
機能ファイルは次のとおりです。
Feature: Test Cucumber with spring
Scenario: First Scenario
Given Some initial condition
Then Nothing happens
上記をそのまま実行すると、すべてが正常に機能し、依存関係(MyService)が問題なくMyStepDefに挿入されます。
このコードを置き換えると:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
以下のコードで(Spring Boot 1.4でそれを処理する新しい方法):
@RunWith(SpringRunner.class)
@SpringBootTest
その後、依存関係(MyService)が注入されることはありません。私はおそらく何かが足りないのですか?
よろしくお願いします!!!
私も同じ問題を抱えていました。上からのコメントは私を解決策に導きました
Cucumber-springの問題のあるコードは、このgithub.com/cucumber/cucumber-jvm/blob/master/spring/src/main/…のようです。
注釈を追加した後@ContextConfiguration
テストは期待どおりに機能しています。
だから私が持っているのは次のとおりです...
@RunWith(Cucumber.class)
@CucumberOptions(plugin = {"json:target/cucumber.json", "pretty"}, features = "src/test/features")
public class CucumberTest {
}
@ContextConfiguration
@SpringBootTest
public abstract class StepDefs {
}
public class MyStepDefs extends StepDefs {
@Inject
Service service;
@Inject
Repository repository;
[...]
}
これがさらにお役に立てば幸いです
Spring Boot 1.5.xと2.0で動作するようにした後、 ブログ投稿を書いた トリッキーなので、これを明確にしようとしました。
まず、明らかな場合でも、プロジェクトに適切な依存関係を含める必要があります(ここでは_cucumber-spring
_が重要です)。たとえば、Mavenの場合:
_<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-Java</artifactId>
<version>2.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>2.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>2.3.1</version>
<scope>test</scope>
</dependency>
_
さて、それを機能させるための重要な部分を要約します:
@RunWith(Cucumber.class
_で注釈が付けられたクラスである必要があります。@Given
_、_@When
_、_@Then
_など)を持つ分離されたクラスにあるステップ定義を使用します。@SpringBootTest
_、@RunWith(SpringRunner.class)
、およびSpringBootでテストを実行するために必要なその他の構成で注釈が付けられた基本クラスを拡張する必要があることです。たとえば、他のレイヤーをモックせずに統合テストを実装する場合は、webEnvironment
構成を追加し、それを_RANDOM_PORT
_または_DEFINED_PORT
_に設定する必要があります。以下の図とコードスケルトンを参照してください。
エントリポイント:
_@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources/features/bag.feature", plugin = {"pretty", "html:target/cucumber"})
public class BagCucumberIntegrationTest {
}
_
Spring Boot基本テストクラス:
_@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public abstract class SpringBootBaseIntegrationTest {
}
_
ステップ定義クラス:
_@Ignore
public class BagCucumberStepDefinitions extends SpringBootBaseIntegrationTest {
// @Given, @When, @Then annotated methods
}
_
これは、DIを機能させるために必要なものです。完全なコード例については、 私のブログ投稿 または GitHubのコード を確認してください。
Spring Boot 1.4より前では、次を使用できます。
@ContextConfiguration(classes = {YourSpringConfiguration.class}, loader = SpringApplicationContextLoader.class)
Spring Boot 1.4以降、SpringApplicationContextLoaderは非推奨になるため、代わりにSpringBootContextLoader.classを使用する必要があります。
実際には、@ SpringBootTest(オプションの構成クラスを含む)を追加するだけでそれ自体で機能するはずですが、cucumber.runtime.Java.spring.SpringFactoryメソッドannotatedWithSupportedSpringRootTestAnnotationsのコードを見ると、そのアノテーションはチェックされていません。そのため、単に追加するだけです。 @SpringBootTestと組み合わせたアノテーションは機能します。
本当にキュウリの春のコードを変更する必要があります。 Springのドキュメントにあるように、SpringApplicationContextLoaderは絶対に必要な場合にのみ使用する必要があると記載されているため、問題を提起できるかどうかを確認します。キュウリのSpringサポートについては、この問題を提起します。
したがって、現状では、@ SpringBootTestと@ContextConfigurationの組み合わせを使用したstripwireの答えが最善の回避策です。
Spring Boot1.5で動作します。構成をあなたと共有したいと思います:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<dependencies>
...
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-Java</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-spring</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
</dependencies>
...
</project>
Feature: User should be greeted
Background:
Given The database is empty
Then All connections are set
Scenario: Default user is greeted
Given A default user
When The application is started
Then The user should be greeted with "Hello Marc!"
@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources", strict = true)
public class CucumberTests { // Classname should end on *Tests
}
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration
abstract class AbstractSpringConfigurationTest {
}
class CucumberGlue : AbstractSpringConfigurationTest() {
@Autowired
lateinit var restTemplate: TestRestTemplate
@Autowired
lateinit var restController: RestController
@Autowired
lateinit var personRepository: PersonRepository
@Autowired
lateinit var entityManager: EntityManager
private var result: String? = null
@Given("^The database is empty$")
fun the_database_is_empty() {
personRepository.deleteAll()
}
@Then("^All connections are set$")
fun all_connections_are_set() {
assertThat(restTemplate).isNotNull()
assertThat(entityManager).isNotNull()
}
@Given("^A default user$")
fun a_default_user() {
}
@When("^The application is started$")
fun the_application_is_started() {
result = restController.testGet()
}
@Then("^The user should be greeted with \"([^\"]*)\"$")
fun the_user_should_be_greeted_with(expectedName: String) {
assertThat(result).isEqualTo(expectedName)
}
}
これは私の構成です、あなたはそれを試すことができます
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@ContextConfiguration(classes = {Application.class})