记录 Spring Boot 中 Spring MVC 的单体测试样例, 方便以后写单体测试直接复制粘贴 包括:
- GET 请求
- GET 请求文件下载
- POST 请求
- POST 请求文件上传
环境准备(Prerequisite)
- JDK 1.8
- Maven 3.5.4
设置(Configuration)
Maven 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
实例详解
单元测试执行过程:
- 准备测试环境
- 通过MockMvc执行请求 3.1. 添加验证断言 3.2. 添加结果处理器 3.3. 得到MvcResult进行自定义断言/进行下一步的异步请求
- 卸载测试环境
被测试类示例
@RestController
@RequestMapping("/foo")
public class FooController {
@Autowired
private FooService fooService;
// HTTP method GET
@GetMapping("/get")
public FooResponse get(@RequestParam(value = "offset") int offset,
@RequestParam(value = "limit") int limit) {
return fooService.get(offset, limit);
}
// HTTP method GET File download
@GetMapping("/get/fileDownload")
public ResponseEntity<InputStreamResource> getFile() throws FileNotFoundException {
File file = fooService.getFile();
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())
.contentType(MediaType.TEXT_PLAIN)
.contentLength(file.length())
.body(resource);
}
// HTTP method POST
@PostMapping("/post")
public FooResponse post(FooRequest fooRequest) {
return fooService.post(fooRequest);
}
// HTTP method POST File Upload
@PostMapping("/post/fileUpload")
public FooResponse postFile(@RequestParam("file") MultipartFile multipartFile) {
if (multipartFile == null || multipartFile.isEmpty())
throw new IllegalArgumentException();
return fooService.postFile(multipartFile);
}
}
Spring MVC 单元测试类示例
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class ControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
FooService fooService;
/**
* 【备选】调用接口获取 token
* @throws Exception
*/
@Before
public void setUp() throws Exception {
MvcResult mvcResult = mockMvc.perform(post("/oauth/token")
.contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.content("username=oauth_admin&password=123456&grant_type=password&redirect_uri=http://www.azh3ng.com&client_id=login&client_secret=secret;")
).andReturn();
UnitTestOAuth2AccessToken oAuth2Token = JsonUtils.deserializeWithNoError(mvcResult.getResponse().getContentAsString(), UnitTestOAuth2AccessToken.class);
token = oAuth2Token.getValue();
}
@After
public void tearDown() throws Exception {
}
private String token;
// HTTP method GET
@Test
public void testHTTPGet() {
FooResponse expectResponse = new FooResponse();
expectResponse.setCode("0");
expectResponse.setMsg("OK");
when(fooService.get(eq("0"), eq("10"))).thenReturn(expectResponse);
try {
MvcResult mvcResult = mockMvc.perform(get("/foo")
.param("offset", "0")
.param("limit", "10")
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk()).andReturn();
verify(this.fooService, times(1)).get(eq("0"), eq("10"));
Assert.assertEquals(JsonUtils.serializeWithNoError(expectResponse), mvcResult.getResponse().getContentAsString());
} catch (Exception e) {
e.printStackTrace();
Assert.fail();
}
}
// HTTP method GET File download
@Test
public void testFileDownload() throws IOException {
File file = new File("download.csv");
if (!file.exists()) {
file.createNewFile();
}
when(fooService.getFile()).thenReturn(file);
try {
MvcResult mvcResult = mockMvc.perform(get("/get/fileDownload")
.header("Authorization", "Bearer " + token))
.andExpect(status().isOk()).andReturn();
verify(fileService, times(1)).getFile();
MockHttpServletResponse response = mvcResult.getResponse();
Assert.assertEquals(HttpStatus.OK.value(), response.getStatus());
Assert.assertEquals("attachment;filename=download.csv", response.getHeader(HttpHeaders.CONTENT_DISPOSITION));
Assert.assertEquals(MediaType.TEXT_PLAIN_VALUE, response.getContentType());
} catch (Exception e) {
e.printStackTrace();
Assert.fail();
} finally {
file.delete();
}
}
// HTTP method POST
@Test
public void testHTTPPost() {
FooResponse expectResponse = new FooResponse();
expectResponse.setCode("0");
expectResponse.setMsg("OK");
when(this.fooService.post(any(FooRequest.class))).thenReturn(expectResponse);
/* Map<String, String> map = new HashMap<>();
map.put("id", "001");
map.put("name", "tom");
String content = JsonUtils.serializeWithNoError(map); */
FooRequest fooRequest = new FooRequest();
fooRequest.setId("001");
fooRequest.setName("tom");
String content = JsonUtils.serializeWithNoError(fooRequest);
try {
MvcResult mvcResult = this.mockMvc.perform(
post("/post")
.content(content)
.contentType(MediaType.APPLICATION_JSON_UTF8)).andExpect(status().isOk())
.andReturn();
verify(this.fooService, times(1)).post(any(FooRequest.class));
Assert.assertEquals(JsonUtils.serialize(expectResponse), mvcResult.getResponse().getContentAsString());
} catch (Exception e) {
e.printStackTrace();
Assert.fail();
}
}
// HTTP method POST File Upload
@Test
public void testFileUpload() {
FooResponse expectResponse = new FooResponse();
expectResponse.setCode("0");
expectResponse.setMsg("OK");
when(fooService.postFile(any(MultipartFile.class))).thenReturn(expectResponse);
try {
MvcResult mvcResult = mockMvc.perform(
MockMvcRequestBuilders
.fileUpload("/post/fileUpload")
.file(
new MockMultipartFile("file", "upload.csv", ",multipart/form-data", "fileContent".getBytes(StandardCharsets.UTF_8))
)
.header("Authorization", "Bearer " + token)
).andExpect(status().isOk())
.andReturn();
verify(this.fooService, times(1)).postFile(any(MultipartFile.class));
Assert.assertEquals(JsonUtils.serializeWithNoError(expectResponse), mvcResult.getResponse().getContentAsString());
} catch (Exception e) {
e.printStackTrace();
Assert.fail();
}
}
}