英文:
Run a spring-boot application and its cucumber tests in the same project using one maven "command"
问题
概述
这是一个使用Spring Boot的Maven项目,项目中包含一些Cucumber测试。
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")
public 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);
}
}
问题
我希望能够发出单个命令来启动SpringBoot应用程序,然后对已启动的应用程序运行测试。在测试完成后,关闭SpringBoot应用程序。
理想情况下,这将用于像Jenkins这样的CI系统。
我正在探索Apache Maven AntRun插件作为一种选择,但这是我第一次进行这种设置,我不确定这是否是正确的方法。之前我看到过类似的设置,但那是在独立的项目中(测试与被测试应用程序不同)。
英文:
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,
- I can run in a console
mvn spring-boot:run
(from where the SpringBoot application starts) - and then in another console
mvn test -Dtest=CucumberTestsRunner
, from where the Cucumber tests run against the webservices
So 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).
答案1
得分: 3
作为使用 `mvn spring-boot:start test spring-boot:stop` 或使用 `mvn verify` 并在 `pre-integration-test` 阶段启动应用程序,然后在 `post-integration-test` 阶段停止应用程序的替代方法,您还可以使用 `cucumber-spring` 并使用 Mock MVC 运行测试。
pom.xml 文件:
<?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>
Application.java 文件:
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!";
}
}
}
CucumberTest.java 文件:
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!")));
}
}
hello.feature 文件:
Feature: Hello world
Scenario: Calling a rest end point
* the application says hello
英文:
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
答案2
得分: 2
不必在一个控制台中使用 "spring-boot:run",并在第二个控制台中运行测试,可以使用spring-boot:start和spring-boot:stop命令。
类似于 mvn spring-boot:start test spring-boot:stop
,将会启动应用程序,运行测试,然后再停止应用程序。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论