SpringBoot MockMVC 单元测试

代码实现

pom.xml

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>

controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.example.demoboot.controller;

import com.example.demoboot.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

/**
* 公众号: 当我遇上你
*
* @author cuishiying
* @date 2021-01-22
*/
@Slf4j
@RestController
public class IndexController {

/**
* http://localhost:8088/hello/1?name=admin
*
* @param id id ID
* @param name 帐号
* @return 测试数据
*/
@GetMapping("/hello/{id}")
public Object hello(@PathVariable Integer id, @RequestParam String name) {
log.info(String.format("hello: id=%d, name=%s", id, name));
return String.format("hello: id=%d, name=%s", id, name);
}

@PostMapping("/submit")
public Object submit(@RequestBody User user) {
log.info(user.toString());
return user;
}
}

user

1
2
3
4
5
6
7
8
/**
* @author cuishiying
* @date 2021-01-22
*/
@Data
public class User {
private String username;
}

单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package com.example.demoboot.controller;

import com.example.demoboot.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.nio.charset.StandardCharsets;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringBootTest
class IndexControllerTest {

protected MockMvc mockMvc;
protected ObjectMapper objectMapper;

public static RequestPostProcessor authentication() {
return request -> {
request.addHeader("Authorization", "123");
return request;
};
}

@BeforeEach
public void setUp(WebApplicationContext webApplicationContext) {
this.mockMvc =
MockMvcBuilders.webAppContextSetup(webApplicationContext).alwaysDo(print()).build();
this.objectMapper = new ObjectMapper();
}

@Test
void hello() throws Exception {
mockMvc.perform(
get("/hello/{id}", 1)
// 设置返回值类型为application/json
.accept(MediaType.APPLICATION_JSON)
// 设置编码为utf-8,否则默认为ISO-8859-1
.characterEncoding(StandardCharsets.UTF_8.name())
// 设置请求参数
.param("name", "admin")
// 设置请求头
.with(authentication()))
// 断言返回状态
.andExpect(status().isOk())
// 断言返回数据包含admin
.andExpect(content().string(containsString("admin")))
.andReturn()
.getResponse()
.getContentAsString();
}

@Test
void submit() throws Exception {
User user = new User();
user.setUsername("当我遇上你");
mockMvc.perform(
post("/submit")
// 设置提交格式为application/json
.contentType(MediaType.APPLICATION_JSON)
// 设置返回值类型为application/json;charset=UTF-8
.accept(
new MediaType(
"application", "json", StandardCharsets.UTF_8))
// 设置编码为utf-8,否则默认为ISO-8859-1
.characterEncoding(StandardCharsets.UTF_8.name())
// 设置请求体
.content(objectMapper.writeValueAsString(user)))
// 断言返回状态
.andExpect(status().isOk())
// 断言返回字段
.andExpect(jsonPath("$.username", is("当我遇上你")))
// 断言返回字段
.andExpect(jsonPath("$.username").value("当我遇上你"))
// 断言返回内容
.andExpect(content().json(objectMapper.writeValueAsString(user)));
}
}

注意

JUnit5 在如上代码中 @BeforeEach 中构建 MockMvc, Filter 是不会生效的。需要按如下配置:

1
2
3
4
5
6
7
@AutoConfigureMockMvc
@SpringBootTest
public class BaseMock {

@Resource
protected MockMvc mockMvc;
}

最后

本文到此结束,感谢阅读。如果您觉得不错,请关注公众号【当我遇上你】,您的支持是我写作的最大动力。