在同一个项目中使用一个Maven “命令”运行Spring Boot应用程序及其Cucumber测试。

huangapple go评论72阅读模式
英文:

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(&quot;/&quot;)
public class Controller {

    @GetMapping(&quot;hello&quot;)
    public String hello() {
        return &quot;Hello!&quot;;
    }
}

CucumberTestsRunner

@RunWith(Cucumber.class)
@CucumberOptions(glue = &quot;cucumbertests&quot;)
pulic class CucumberTestsRunner {
}

StepDefinitions

public class StepDefinitions {

    private String response;

    @When(&quot;I say hello&quot;)
    public void iSayHello() {
        // rest assured call
        response = get(&quot;&lt;base_url&gt;/hello&quot;).extract().asString();
    }

    @Then
    public void iMGreetedWithHello() {
        assertEquals(&quot;Hello!&quot;, 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
│&#160;&#160; └── java
│&#160;&#160;     └── com
│&#160;&#160;         └── example
│&#160;&#160;             └── Application.java
└── test
├── java
│&#160;&#160; └── com
│&#160;&#160;     └── example
│&#160;&#160;         └── CucumberTest.java
└── resources
├── com
│&#160;&#160; └── example
│&#160;&#160;     └── hello.feature
└── junit-platform.properties
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;
xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
&lt;parent&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
&lt;version&gt;2.3.1.RELEASE&lt;/version&gt;
&lt;/parent&gt;
&lt;groupId&gt;com.example&lt;/groupId&gt;
&lt;artifactId&gt;com.example&lt;/artifactId&gt;
&lt;version&gt;1.0.0-SNAPSHOT&lt;/version&gt;
&lt;properties&gt;
&lt;java.version&gt;11&lt;/java.version&gt;
&lt;cucumber.version&gt;6.5.0&lt;/cucumber.version&gt;
&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
&lt;/properties&gt;
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;io.cucumber&lt;/groupId&gt;
&lt;artifactId&gt;cucumber-java&lt;/artifactId&gt;
&lt;version&gt;${cucumber.version}&lt;/version&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;io.cucumber&lt;/groupId&gt;
&lt;artifactId&gt;cucumber-spring&lt;/artifactId&gt;
&lt;version&gt;${cucumber.version}&lt;/version&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;io.cucumber&lt;/groupId&gt;
&lt;artifactId&gt;cucumber-junit-platform-engine&lt;/artifactId&gt;
&lt;version&gt;${cucumber.version}&lt;/version&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;/project&gt;
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(&quot;/&quot;)
public String local() {
return &quot;Greetings from Local!&quot;;
}
}
}
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(&quot;the application says hello&quot;)
public void getLocalHello() throws Exception {
mvc.perform(get(&quot;/&quot;).accept(APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo(&quot;Greetings from Local!&quot;)));
}
}
Feature: Hello world
Scenario: Calling a rest end point
* the application says hello

答案2

得分: 2

不必在一个控制台中使用 "spring-boot:run",并在第二个控制台中运行测试,可以使用spring-boot:startspring-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.

huangapple
  • 本文由 发表于 2020年8月17日 15:54:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/63446770.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定