├── .github └── FUNDING.yml ├── .gitignore ├── README.md ├── images └── cucumber-spring-boot.png ├── pom.xml └── src ├── main ├── java │ └── io │ │ └── tpd │ │ └── springbootcucumber │ │ ├── Bag.java │ │ ├── BagController.java │ │ └── SpringBootCucumberApplication.java └── resources │ └── application.properties └── test ├── java └── io │ └── tpd │ └── springbootcucumber │ ├── bagbasics │ ├── BagCucumberIntegrationTest.java │ └── BagCucumberStepDefinitions.java │ ├── bagcommons │ ├── BagCommonCucumberStepDefinitions.java │ ├── BagHttpClient.java │ └── CucumberSpringConfiguration.java │ └── bagextra │ ├── BagExtraCucumberIntegrationTest.java │ └── BagExtraCucumberStepDefinitions.java └── resources └── features ├── bagbasics └── bag.feature └── bagextra └── bag-more.feature /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: mechero 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cucumber in Spring Boot using Dependency Injection 2 | 3 | This code sample shows how to use Dependency Injection in Cucumber within a Spring Boot application. 4 | 5 | You can find the complete instructions on this post at The Practical Developer site: [Cucumber Tests with Dependency Injection using Spring Boot](https://thepracticaldeveloper.com/cucumber-tests-spring-boot-dependency-injection//) 6 | 7 | ![Cucumber and Dependency Injection in a Spring Boot App - The Practical Developer](images/cucumber-spring-boot.png) 8 | -------------------------------------------------------------------------------- /images/cucumber-spring-boot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mechero/spring-boot-cucumber/88989d101d3693973896fb7e3bc23400a526f985/images/cucumber-spring-boot.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | io.tpd 7 | spring-boot-cucumber 8 | 1.0.0-SNAPSHOT 9 | jar 10 | 11 | spring-boot-cucumber 12 | Demo project using Cucumber DI and Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.0.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 6.8.1 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 34 | io.cucumber 35 | cucumber-java 36 | ${cucumber.version} 37 | test 38 | 39 | 40 | io.cucumber 41 | cucumber-junit 42 | ${cucumber.version} 43 | test 44 | 45 | 46 | io.cucumber 47 | cucumber-spring 48 | ${cucumber.version} 49 | test 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-test 54 | test 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-maven-plugin 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/io/tpd/springbootcucumber/Bag.java: -------------------------------------------------------------------------------- 1 | package io.tpd.springbootcucumber; 2 | 3 | import java.util.ArrayList; 4 | 5 | public final class Bag { 6 | 7 | private final ArrayList things; 8 | 9 | Bag() { 10 | things = new ArrayList<>(); 11 | } 12 | 13 | void add(final String something) { 14 | things.add(something); 15 | } 16 | 17 | public ArrayList getThings() { 18 | return things; 19 | } 20 | 21 | public boolean isEmpty() { 22 | return things.isEmpty(); 23 | } 24 | 25 | public void removeEverything() { 26 | things.clear(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/tpd/springbootcucumber/BagController.java: -------------------------------------------------------------------------------- 1 | package io.tpd.springbootcucumber; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.*; 5 | 6 | @RestController 7 | @RequestMapping("/things") 8 | public final class BagController { 9 | 10 | private final Bag bag = new Bag(); 11 | 12 | @GetMapping 13 | public Bag getBag() { 14 | return bag; 15 | } 16 | 17 | @PostMapping 18 | @ResponseStatus(HttpStatus.CREATED) 19 | public void addThing(@RequestBody final String something) { 20 | bag.add(something); 21 | } 22 | 23 | @DeleteMapping 24 | public void removeEverything() { 25 | bag.removeEverything(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/io/tpd/springbootcucumber/SpringBootCucumberApplication.java: -------------------------------------------------------------------------------- 1 | package io.tpd.springbootcucumber; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootCucumberApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootCucumberApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mechero/spring-boot-cucumber/88989d101d3693973896fb7e3bc23400a526f985/src/main/resources/application.properties -------------------------------------------------------------------------------- /src/test/java/io/tpd/springbootcucumber/bagbasics/BagCucumberIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package io.tpd.springbootcucumber.bagbasics; 2 | 3 | import io.cucumber.junit.Cucumber; 4 | import io.cucumber.junit.CucumberOptions; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(Cucumber.class) 8 | @CucumberOptions(features = "src/test/resources/features/bagbasics", 9 | plugin = {"pretty", "html:target/cucumber/bagbasics"}, 10 | extraGlue = "io.tpd.springbootcucumber.bagcommons") 11 | public class BagCucumberIntegrationTest { 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/io/tpd/springbootcucumber/bagbasics/BagCucumberStepDefinitions.java: -------------------------------------------------------------------------------- 1 | package io.tpd.springbootcucumber.bagbasics; 2 | 3 | import io.cucumber.java.en.Then; 4 | import io.cucumber.java.en.When; 5 | import io.tpd.springbootcucumber.bagcommons.BagHttpClient; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.HttpStatus; 10 | 11 | import java.util.Collections; 12 | import java.util.List; 13 | import java.util.stream.IntStream; 14 | 15 | import static org.assertj.core.api.Assertions.assertThat; 16 | 17 | public class BagCucumberStepDefinitions { 18 | 19 | private final Logger log = LoggerFactory.getLogger(BagCucumberStepDefinitions.class); 20 | 21 | @Autowired 22 | private BagHttpClient bagHttpClient; 23 | 24 | @When("^I put (\\d+) (\\w+) in the bag$") 25 | public void i_put_something_in_the_bag(final int quantity, final String something) { 26 | IntStream.range(0, quantity) 27 | .peek(n -> log.info("Putting a {} in the bag, number {}", something, quantity)) 28 | .map(ignore -> bagHttpClient.put(something)) 29 | .forEach(statusCode -> assertThat(statusCode).isEqualTo(HttpStatus.CREATED.value())); 30 | } 31 | 32 | @Then("^the bag should contain only (\\d+) (\\w+)$") 33 | public void the_bag_should_contain_only_something(final int quantity, final String something) { 34 | assertNumberOfTimes(quantity, something, true); 35 | } 36 | 37 | @Then("^the bag should contain (\\d+) (\\w+)$") 38 | public void the_bag_should_contain_something(final int quantity, final String something) { 39 | assertNumberOfTimes(quantity, something, false); 40 | } 41 | 42 | private void assertNumberOfTimes(final int quantity, final String something, final boolean onlyThat) { 43 | final List things = bagHttpClient.getContents().getThings(); 44 | log.info("Expecting {} times {}. The bag contains {}", quantity, something, things); 45 | final int timesInList = Collections.frequency(things, something); 46 | assertThat(timesInList).isEqualTo(quantity); 47 | if (onlyThat) { 48 | assertThat(timesInList).isEqualTo(things.size()); 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/io/tpd/springbootcucumber/bagcommons/BagCommonCucumberStepDefinitions.java: -------------------------------------------------------------------------------- 1 | package io.tpd.springbootcucumber.bagcommons; 2 | 3 | import io.cucumber.java.en.Given; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | 6 | import static org.assertj.core.api.Assertions.assertThat; 7 | 8 | public class BagCommonCucumberStepDefinitions { 9 | 10 | @Autowired 11 | private BagHttpClient bagHttpClient; 12 | 13 | @Given("^the bag is empty$") 14 | public void the_bag_is_empty() { 15 | bagHttpClient.clean(); 16 | assertThat(bagHttpClient.getContents().isEmpty()).isTrue(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/io/tpd/springbootcucumber/bagcommons/BagHttpClient.java: -------------------------------------------------------------------------------- 1 | package io.tpd.springbootcucumber.bagcommons; 2 | 3 | import io.tpd.springbootcucumber.Bag; 4 | import org.springframework.boot.web.server.LocalServerPort; 5 | import org.springframework.context.annotation.Scope; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.client.RestTemplate; 8 | 9 | import static io.cucumber.spring.CucumberTestContext.SCOPE_CUCUMBER_GLUE; 10 | 11 | @Component 12 | @Scope(SCOPE_CUCUMBER_GLUE) 13 | public class BagHttpClient { 14 | 15 | private final String SERVER_URL = "http://localhost"; 16 | private final String THINGS_ENDPOINT = "/things"; 17 | 18 | @LocalServerPort 19 | private int port; 20 | private final RestTemplate restTemplate = new RestTemplate(); 21 | 22 | 23 | private String thingsEndpoint() { 24 | return SERVER_URL + ":" + port + THINGS_ENDPOINT; 25 | } 26 | 27 | public int put(final String something) { 28 | return restTemplate.postForEntity(thingsEndpoint(), something, Void.class).getStatusCodeValue(); 29 | } 30 | 31 | public Bag getContents() { 32 | return restTemplate.getForEntity(thingsEndpoint(), Bag.class).getBody(); 33 | } 34 | 35 | public void clean() { 36 | restTemplate.delete(thingsEndpoint()); 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/io/tpd/springbootcucumber/bagcommons/CucumberSpringConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.tpd.springbootcucumber.bagcommons; 2 | 3 | import io.cucumber.spring.CucumberContextConfiguration; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @CucumberContextConfiguration 7 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 8 | public class CucumberSpringConfiguration { 9 | } 10 | -------------------------------------------------------------------------------- /src/test/java/io/tpd/springbootcucumber/bagextra/BagExtraCucumberIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package io.tpd.springbootcucumber.bagextra; 2 | 3 | import io.cucumber.junit.Cucumber; 4 | import io.cucumber.junit.CucumberOptions; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(Cucumber.class) 8 | @CucumberOptions(features = "src/test/resources/features/bagextra", 9 | plugin = {"pretty", "html:target/cucumber/bagextra"}, 10 | extraGlue = "io.tpd.springbootcucumber.bagcommons") 11 | public class BagExtraCucumberIntegrationTest { 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/io/tpd/springbootcucumber/bagextra/BagExtraCucumberStepDefinitions.java: -------------------------------------------------------------------------------- 1 | package io.tpd.springbootcucumber.bagextra; 2 | 3 | import io.cucumber.java.en.Given; 4 | import io.cucumber.java.en.When; 5 | import io.tpd.springbootcucumber.bagcommons.BagHttpClient; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | public class BagExtraCucumberStepDefinitions { 11 | 12 | @Autowired 13 | private BagHttpClient bagHttpClient; 14 | 15 | @Given("^the bag is not empty$") 16 | public void the_bag_is_not_empty() { 17 | bagHttpClient.put("something"); 18 | assertThat(bagHttpClient.getContents().isEmpty()).isFalse(); 19 | } 20 | 21 | @When("^I empty the bag$") 22 | public void empty_the_bag() { 23 | bagHttpClient.clean(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/resources/features/bagbasics/bag.feature: -------------------------------------------------------------------------------- 1 | Feature: Bag functionalities 2 | 3 | Scenario: Putting one thing in the bag 4 | Given the bag is empty 5 | When I put 1 potato in the bag 6 | Then the bag should contain only 1 potato 7 | 8 | Scenario: Putting few things in the bag 9 | Given the bag is empty 10 | When I put 1 potato in the bag 11 | And I put 2 cucumber in the bag 12 | Then the bag should contain 1 potato 13 | And the bag should contain 2 cucumber -------------------------------------------------------------------------------- /src/test/resources/features/bagextra/bag-more.feature: -------------------------------------------------------------------------------- 1 | Feature: Bag more functionalities 2 | 3 | Scenario: Putting one thing in the bag 4 | Given the bag is not empty 5 | When I empty the bag 6 | Then the bag is empty 7 | --------------------------------------------------------------------------------