Reputation: 300
Overview
A maven project using spring boot for which some cucumber tests are implemented (in the same project!).
src
|
|-main
| |
| |-java
| |
| |-SpringBootApp
| |-Controller
|
|-test
|
|-java
| |
| |-cucumbertests
| |
| |-StepDefinitions
| |-CucumberTestsRunner
|
|-resources
|-features
|-hello.feature
Controller
@RestController
@RequestMapping("/")
public class Controller {
@GetMapping("hello")
public String hello() {
return "Hello!";
}
}
CucumberTestsRunner
@RunWith(Cucumber.class)
@CucumberOptions(glue = "cucumbertests")
pulic class CucumberTestsRunner {
}
StepDefinitions
public class StepDefinitions {
private String response;
@When("I say hello")
public void iSayHello() {
// rest assured call
response = get("<base_url>/hello").extract().asString();
}
@Then
public void iMGreetedWithHello() {
assertEquals("Hello!", response);
}
}
With this in place,
mvn spring-boot:run
(from where the SpringBoot application starts)mvn test -Dtest=CucumberTestsRunner
, from where the Cucumber tests run against the webservicesSo far so good, the tests pass without any issue.
Problem
I'd like to be able to issue a single command to start the SpringBoot application and then run the tests against the started application. Then after the tests finished, kill the SpringBoot application.
Ideally this is intended to be used in a CI system like Jenkins.
I was exploring the Apache Maven AntRun plugin as an option, but this is my first time doing this kind of set up and I'm not sure this would be a right approach. Previously I have seen set up like this but on independent projects (tests in a different app than the tested application).
Upvotes: 2
Views: 7624
Reputation: 12049
As an alternative to using mvn spring-boot:start test spring-boot:stop
or to using mvn verify
and starting the application in the pre-integration-test
and stopping it in the post-integration-test
phase you can also use cucumber-spring
and run the test with Mock MCV.
├── pom.xml
└── src
├── main
│ └── java
│ └── com
│ └── example
│ └── Application.java
└── test
├── java
│ └── com
│ └── example
│ └── CucumberTest.java
└── resources
├── com
│ └── example
│ └── hello.feature
└── junit-platform.properties
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
</parent>
<groupId>com.example</groupId>
<artifactId>com.example</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<cucumber.version>6.5.0</cucumber.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<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-spring</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit-platform-engine</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
package com.example;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class Application {
@RestController
public static class HelloController {
@RequestMapping("/")
public String local() {
return "Greetings from Local!";
}
}
}
package com.example;
import io.cucumber.java.en.Given;
import io.cucumber.junit.platform.engine.Cucumber;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Cucumber
@CucumberContextConfiguration
@SpringBootTest
@AutoConfigureMockMvc
public class CucumberTest {
@Autowired
private MockMvc mvc;
@Given("the application says hello")
public void getLocalHello() throws Exception {
mvc.perform(get("/").accept(APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Local!")));
}
}
Feature: Hello world
Scenario: Calling a rest end point
* the application says hello
Upvotes: 3
Reputation: 236
Instead of using spring-boot:run in one console and running your tests in a second one, you can use use spring-boot:start and spring-boot:stop.
Something like mvn spring-boot:start test spring-boot:stop
would start the application, run the tests and then stop the application again.
Upvotes: 2