本文主要是记录在 Spring Boot 项目中如何简单使用单元测试
,对于相关的原理及知识暂不介绍。行文仓促,若有不妥之处,望各位大佬不吝赐教。
一、搭建 Spring Boot 项目
这里展示部分代码,注意所用的数据库表(user
)含有 user_id、user_name
两个字段。
- UserController.java
package com.example.study.unitteststudy.controller;
import com.example.study.unitteststudy.domain.User;
import com.example.study.unitteststudy.service.UserService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author yi
* @date 2021/9/13 19:54
*/
@RestController
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("/user")
public User addUser(@RequestBody User user) {
userService.add(user);
// 直接返回以方便测试数据
return user;
}
}
- UserController,java
package com.example.study.unitteststudy.controller;
import com.alibaba.fastjson.JSON;
import com.example.study.unitteststudy.domain.User;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
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.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void addUser() throws Exception {
User user = new User(6, "小红");
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/user")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(JSON.toJSON(user).toString());
ResultActions resultActions = mockMvc.perform(requestBuilder);
resultActions.andReturn().getResponse().setCharacterEncoding("UTF-8");
resultActions.andDo(print()).andExpect(status().isOk());
}
}
结果如下所示:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /user
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"32"]
Body = {"userName":"小红","userId":6}
Session Attrs = {}
Handler:
Type = com.example.study.unitteststudy.controller.UserController
Method = com.example.study.unitteststudy.controller.UserController#addUser(User)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"application/json;charset=UTF-8"]
Content type = application/json
Body = {"userId":6,"userName":"小红"}
Forwarded URL = null
Redirected URL = null
Cookies = []
2021-09-13 21:32:07.839 INFO 11108 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@2034b64c testClass = UserControllerTest, testInstance = com.example.study.unitteststudy.controller.UserControllerTest@6f044c58, testMethod = addUser@UserControllerTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@75d3a5e0 testClass = UserControllerTest, locations = '{}', classes = '{class com.example.study.unitteststudy.UnitTestStudyApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@74d1dc36 key = [org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@61df66b6, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@2f7298b, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@dbf57b3, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@4b3fa0b3, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@661972b0, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@27082746], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]
从上面的结果中可以看出已成功实现测试功能。
二、总结
1.本文用的是 Junit5
,主要注解如下。
- 在测试类上面加上这三个注解就可以进行接口的测试了,其中
@AutoConfigureMockMvc
是用来配置MockMvc
的,而 MockMvc 是来模拟执行 HTTP 请求的。
@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
- 由于涉及数据库,在测试时一般不想改变数据库,于是加上注解让其自动回滚
@Transactional
3.在发送 post
请求时需注意 json 与 object 的互转以及转 string
。
4.在单元测试中用断言来进行判断,而非自己把某些结果输出来去判断。
2021.09.13