测试 Web 层
测试 Web 层
您将构建一个简单的 Spring 应用程序并使用 JUnit 对其进行测试。您可能已经知道如何编写和运行应用程序中各个类的单元测试,因此,对于本指南,我们将专注于使用 Spring Test 和 Spring Boot 功能来测试 Spring 和您的代码之间的交互。您将从应用程序上下文成功加载的简单测试开始,然后继续使用 Spring 的 MockMvc 仅测试 Web 层。大量会用到mock方法,与大多数 Spring 入门指南一样,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。无论哪种方式,您最终都会得到有效的代码
下载代码
git clone https://github.com/spring-guides/gs-testing-web.git
Cloning into 'gs-testing-web'...
remote: Enumerating objects: 620, done.
remote: Counting objects: 100% (39/39), done.
remote: Compressing objects: 100% (25/25), done.
remote: Total 620 (delta 17), reused 27 (delta 12), pack-reused 581 eceiving objects: 97% (602/620), 780.01 KiB | 272.00 KiB/s
Receiving objects: 100% (620/620), 855.83 KiB | 299.00 KiB/s, done.
Resolving deltas: 100% (375/375), done.
build.gradle
以下清单显示了在您选择 Gradle 时创建的
plugins{
id'org.springframework.boot' version'2.5.2'
id'io.spring.dependency-management' version'1.0.11.RELEASE'
id'java'
}
group ='com.example'
version ='0.0.1-SNAPSHOT'
sourceCompatibility ='1.8'
repositories{
mavenCentral()
}
dependencies{
implementation'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test')
}
test{
useJUnitPlatform()
}
创建一个简单的应用程序
package com.example.testingweb;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HomeController {
@RequestMapping("/")
public @ResponseBody Stringgreeting() {
return "Hello, World";
}
@RequestMapping("/add")
public @ResponseBody Stringadd() {
return "add users";
}
}
前面的示例没有指定 GET 与 PUT、POST 等。默认情况下,@RequestMapping 映射所有 HTTP 操作。您可以使用 @GetMapping 或 @RequestMapping(method=GET) 来缩小此映射的范围。
运行应用程序
package com.example.testingweb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TestingWebApplication {
public static void main(String[] args) {
SpringApplication.run(TestingWebApplication.class, args);
}
}
@SpringBootApplication 是一个方便的注解,它添加了以下所有内容:@Configuration:将类标记为应用程序上下文的 bean 定义源。
@EnableAutoConfiguration:告诉 Spring Boot 根据类路径设置、其他 bean 和各种属性设置开始添加 bean。
@EnableWebMvc:将应用程序标记为 Web 应用程序并激活关键行为,例如设置 DispatcherServlet。
Spring Boot 在类路径上看到 spring-webmvc 时会自动添加它。
@ComponentScan:告诉 Spring 在 com.example.testingweb 包中查找其他组件、配置和服务,让它找到 HelloController 类
main() 方法使用 Spring Boot 的 SpringApplication.run() 方法来启动应用程序。您是否注意到没有一行 XML?也没有 web.xml 文件。该 Web 应用程序是 100% 纯 Java 的,您无需处理任何管道或基础设施的配置。 Spring Boot 为您处理所有这些
碰到下面的编译错误:
> startup failed:
General error during semantic analysis: Unsupported class file major version 60
java.lang.IllegalArgumentException: Unsupported class file major version 60
不用着急,重新配置一下jdk的版本就可以。
@SpringBootTest 注释告诉 Spring Boot 寻找一个主要的配置类(例如一个带有 @SpringBootApplication 的类)并使用它来启动一个 Spring 应用程序上下文。您可以在 IDE 或命令行上运行此测试(通过运行 ./mvnw test 或 ./gradlew test),它应该会通过。为了让自己相信上下文正在创建您的控制器,您可以添加一个断言,如以下示例(来自 src/test/java/com/example/testingweb/SmokeTest.java)所示:
冒烟测试
package com.example.testingweb;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class SmokeTest {
@Autowired
private HomeControllercontroller;
@Test
public void contextLoads()throws Exception {
if (controller!=null){
System.out.println("controller is not null.");
assertThat(controller).isNotNull();
}else{
System.out.println("controller is null.");
assertThat(controller).isNull();
}
}
}
返回结果都是controller is not null.
测试Http
进行健全性检查固然很好,但您还应该编写一些断言应用程序行为的测试。为此,您可以启动应用程序并侦听连接(就像在生产中所做的那样),然后发送 HTTP 请求并断言响应。以下清单(来自 src/test/java/com/example/testingweb/HttpRequestTest.java)显示了如何执行此操作:
请注意使用 webEnvironment=RANDOM_PORT 以随机端口启动服务器(有助于避免测试环境中的冲突)以及使用 @LocalServerPort 注入端口。另请注意,Spring Boot 已自动为您提供 TestRestTemplate。您所要做的就是向其中添加@Autowired
package com.example.testingweb;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class HttpRequestTest {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplaterestTemplate;
@Test
public void greetingShouldReturnDefaultMessage()throws Exception {
assertThat(this.restTemplate.getForObject("http://localhost:" +port +"/",
String.class)).contains("Hello, World");
}
@Test
public void addReturnDefaultMessage()throws Exception {
assertThat(this.restTemplate.getForObject("http://localhost:" +port +"/add",
String.class)).contains("add users");
}
}