在UTDD的流程中,通常会从上到下进行模拟,流程如下:
Controller接口单元测试
–》Controller接口代码实现
–》Api接口单元测试
–》Api接口代码实现
那么我们先从Controller的单元测试模拟开始:
一、MockMvc功能介绍:
MockMvc是由spring-test包提供,实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,使得测试速度快、不依赖网络环境。同时提供了一套验证的工具,结果的验证十分方便。
接口MockMvcBuilder,提供一个唯一的build方法,用来构造MockMvc。
主要有两个实现:StandaloneMockMvcBuilder和DefaultMockMvcBuilder,分别对应两种测试方式,即独立安装和集成Web环境测试(并不会集成真正的web环境,而是通过相应的Mock API进行模拟测试,无须启动服务器)。
MockMvcBuilders提供了对应的创建方法standaloneSetup方法和webAppContextSetup方法,在使用时直接调用即可。
二、代码示例:
首先是pom坐标:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>loan-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>loan-server</name>
<description>loan-server</description>
<properties>
<java.version>1.8</java.version>
<testcontainers.version>1.16.0</testcontainers.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.24</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<exclusions>
<exclusion>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
</exclusion>
</exclusions>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jmockit/jmockit -->
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.197</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>${testcontainers.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.Controller接口测试类:
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
@SpringBootTest(classes = LoanServerApplication.class)//这里放启动类
public class LoanControllerTest {
MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilter(((request, response, chain) -> {
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
})).build();
}
@Test
public void should_get_userLoanPlan_success_byGet() throws Exception {
String result = mockMvc.perform(
get("/loan-plans/{idCard}", "412233333333"))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();
String expected = "{\"createdAt\":\"2021-11-23T00:41:49.257479\",\"gender\":\"MALE\",\"houseMaterial\":{\"age\":0,\"price\":10000},\"id\":1,\"idCard\":\"412233333333\",\"income\":10000,\"lenderAge\":35,\"name\":\"王一\",\"togetherLender\":{\"idCard\":\"111111111\",\"income\":10000},\"updatedAt\":\"2021-11-23T00:41:49.257512\"}";
JSONComparator comparator = new CustomComparator(JSONCompareMode.LENIENT,
new Customization("id", (o1, o2) -> true),
new Customization("createdAt", (o1, o2) -> true),
new Customization("updatedAt", (o1, o2) -> true)
);
JSONAssert.assertEquals(expected, result, comparator);
}
@Test
public void should_get_userLoanPlan_success_byPost() throws Exception {
String result = mockMvc.perform(
post("/loan-plans/{idCard}", "412233333333"))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();
String expected = "{\"createdAt\":\"2021-11-23T00:41:49.257479\",\"gender\":\"MALE\",\"houseMaterial\":{\"age\":0,\"price\":10000},\"id\":1,\"idCard\":\"412233333333\",\"income\":10000,\"lenderAge\":35,\"name\":\"王一\",\"togetherLender\":{\"idCard\":\"111111111\",\"income\":10000},\"updatedAt\":\"2021-11-23T00:41:49.257512\"}";
JSONComparator comparator = new CustomComparator(JSONCompareMode.LENIENT,
new Customization("id", (o1, o2) -> true),
new Customization("createdAt", (o1, o2) -> true),
new Customization("updatedAt", (o1, o2) -> true)
);
JSONAssert.assertEquals(expected, result, comparator);
}
}
3、Controller接口代码
@RestController
@RequestMapping("loan-plans")
public class LoanController {
@GetMapping("/{idCard}")
public JSONObject getUserLoadPlanMaterial(@PathVariable String idCard) {
String result = "{\"createdAt\":\"2021-10-23T00:41:49.257479\",\"gender\":\"MALE\",\"houseMaterial\":{\"age\":0,\"price\":10000},\"id\":1,\"idCard\":\"412233333333\",\"income\":10000,\"lenderAge\":35,\"name\":\"王一\",\"togetherLender\":{\"idCard\":\"111111111\",\"income\":10000},\"updatedAt\":\"2021-10-23T00:41:49.257512\"}";
return JSONObject.parseObject(result);
}
@PostMapping("/{idCard}")
public JSONObject Test(@PathVariable String idCard) {
String result = "{\"createdAt\":\"2021-10-23T00:41:49.257479\",\"gender\":\"MALE\",\"houseMaterial\":{\"age\":0,\"price\":10000},\"id\":1,\"idCard\":\"412233333333\",\"income\":10000,\"lenderAge\":35,\"name\":\"王一\",\"togetherLender\":{\"idCard\":\"111111111\",\"income\":10000},\"updatedAt\":\"2021-10-23T00:41:49.257512\"}";
return JSONObject.parseObject(result);
}
}
这里我们通过MockMvc实现了一个简单的get/post请求接口的模拟及单元测试的编写~ 有兴趣的可以尝试一下~ 还可以拓展一些其他接口的单元测试~
喜欢的朋友欢迎一键三连。我们一起学习,进步~~