您好,登錄后才能下訂單哦!
前言
springboot提供了 spirng-boot-starter-test 以供開發者使用單元測試,在引入 spring-boot-starter-test 依賴后:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
其中包含以下幾個庫:
下面我們將從Service層和Controller層的角度來簡單介紹下單元測試
Service單元測試
在SpringBoot 2.0中,創建一個Service的單元測試,代碼如下:
@RunWith(SpringRunner.class) @SpringBootTest public class UserServiceImplTest { @Autowired private UserService userService; @Test public void insertUser() { User user = new User(); user.setUsername("li ning"); user.setPassword("123456"); userService.insertUser(user); } }
上面的測試非常簡單,主要需要注意兩個注解: @RunWith 和 @SpringBootTest
使用 @SpringBootTest 的 webEnvironment 屬性定義運行環境:
Controller的單元測試
首先創建一個Controller,代碼如下:
@RestController public class UserController { @Autowired private UserService userService; @PostMapping("/user") public String userMapping(@RequestBody User user){ userService.insertUser(user); return "ok"; } }
然后創建Controller的單元測試,一般有兩種創建方法。
第一種使用模擬環境進行測試
默認情況下,@SpringBootTest 不會啟動服務器,如果需針對此模擬環境測試Web端點,可以如下配置 MockMvc:
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class UserControllerTest { @Autowired private MockMvc mockMvc; @Test public void userMapping() throws Exception { String content = "{\"username\":\"pj_mike\",\"password\":\"123456\"}"; mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.POST, "/user") .contentType("application/json").content(content)) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.content().string("ok")); } }
這里有一個 @AutoConfigureMockMvc 注解,該注解表示啟動測試的時候自動注入 MockMvc ,而這個 MockMvc 有以下幾個基本的方法:
這里有一個小技巧,一般來說對于一個controller中往往有不止一個Request請求需要測試,敲打MockMvcRequestBuilders與MockMvcResultMatchers會顯得比較繁瑣,有一個簡便的方法就是將這兩個類的方法使用 import static 靜態導入,然后就可以直接使用兩個類的靜態方法了。然后代碼就變成如下所示:
... import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class UserControllerTest { @Autowired private MockMvc mockMvc; @Test public void userMapping() throws Exception { String content = "{\"username\":\"pj_mike\",\"password\":\"123456\"}"; mockMvc.perform(request(HttpMethod.POST, "/user") .contentType("application/json").content(content)) .andExpect(status().isOk()) .andExpect(content().string("ok")); } }
另外,如果是只想關注Web層而不是啟動完整的ApplicationContext,可以考慮使用 @WebMvcTest 注解,該注解不能與@SpringBootTest搭配使用,而且它只關注Web層面,至于涉及到數據層的時候,需要引入相關依賴,關于這個注解更多的介紹請參閱官方文檔: https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests
使用MockMvcBuilder構建MockMvc對象
除了上面用 @AutoConfigureMockMvc 注解直接自動注入 MockMvc的方式,我們還可以利用MockMvcBuilder來構建MockMvc對象,示例代碼如下:
@RunWith(SpringRunner.class) @SpringBootTest public class UserControllerTest4 { @Autowired private WebApplicationContext web; private MockMvc mockMvc; @Before public void setupMockMvc() { mockMvc = MockMvcBuilders.webAppContextSetup(web).build(); } @Test public void userMapping() throws Exception { String content = "{\"username\":\"pj_m\",\"password\":\"123456\"}"; mockMvc.perform(request(HttpMethod.POST, "/user") .contentType("application/json").content(content)) .andExpect(status().isOk()) .andExpect(content().string("ok")); } }
第二種使用真實Web環境進行測試
在@SpringBootTest注解中設置屬性 webEnvironment = WebEnvironment.RANDOM_PORT ,每次運行的時候會隨機選擇一個可用端口。我們也可以還使用 @LoalServerPort 注解用于本地端口號。下面是測試代碼:
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class UserControllerTest3 { @Autowired private TestRestTemplate testRestTemplate; @Test public void userMapping() throws Exception { User user = new User(); user.setUsername("pj_pj"); user.setPassword("123456"); ResponseEntity<String> responseEntity = testRestTemplate.postForEntity("/user", user, String.class); System.out.println("Result: "+responseEntity.getBody()); System.out.println("狀態碼: "+responseEntity.getStatusCodeValue()); } }
上面的代碼中有一個關鍵的類—— TestRestTemplate , TestRestTemplate是Spring的RestTemplate的一種替代品,可用于集成測試,更RestTemplate的使用功能方法類似,一般用于真實web環境測試中,關于該類更加詳細的用法參考官方文檔: https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#boot-features-test-scope-dependencies
單元測試回滾
單元測試的時候,如果不想造成垃圾數據,可以開啟事務功能,在方法或類頭部添加 @Transactional 注解即可,在官方文檔中對此也有說明:
If your test is @Transactional, it rolls back the transaction at the end of each test method by default. However, as using this arrangement with either RANDOM_PORT or DEFINED_PORT implicitly provides a real servlet environment, the HTTP client and server run in separate threads and, thus, in separate transactions. Any transaction initiated on the server does not roll back in this case
解讀一下,在單元測試中使用 @Transactional 注解,默認情況下在測試方法的末尾會回滾事務。然而有一些特殊情況需要注意,當我們使用 RANDOM_PORT 或 DEFINED_PORT 這種安排隱式提供了一個真正的Servlet環境,所以HTTP客戶端和服務器將在不同的線程中運行,從而分離事務,這種情況下,在服務器上啟動的任何事務都不會回滾。
當然如果你想關閉回滾,只要加上 @Rollback(false) 注解即可, @Rollback 表示事務執行完回滾,支持傳入一個value,默認true即回滾,false不回滾。
還有一種情況需要注意,就是如果你使用的數據庫是MySQL,有時候會發現加了注解 @Transactionl 也不會回滾,那么你就要查看一下你的默認引擎是不是InnoDB,如果不是就要改成 InnoDB。
MyISAM 與 InnoDB是mysql目前比較常用的兩個數據庫引擎,MyISAM與InnoDB的主要的不同點在于性能和事務控制上,這里簡單介紹下兩者的區別與轉換方法:
如果你的數據表是MyISAM引擎,由于它不支持事務,在單元測試中添加事務注解,測試方法也是不會回滾的。
修改默認引擎
查看MySQL當前默認的存儲引擎
mysql> show variables like '%storage_engine%';
看具體的表user表用了什么引擎(engine后面的就表示當前表的存儲引擎)
mysql> show create table user;
將user表修為InnoDB存儲引擎
mysql> ALTER TABLE user ENGINE=INNODB;
注意
這里還有一點需要注意的地方, 當我們使用Spring Data JPA時,如果沒有指定MySQL建表時的存儲引擎,默認情況下會使用MySQL的MyISAM ,這也是一個坑點,這種情況下,你在單元測試使用 @Transactional 注解,回滾不會起作用。
解決方法是將 hibernate.dialect 屬性配置成 hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect ,指定MySQL建表的時候使用 InnoDB引擎,示例配置文件如下:
spring: jpa: # 數據庫類型 database: mysql # 輸出日志 show-sql: true properties: hibernate: # JPA配置 hbm2ddl.auto: update # mysql存儲類型配置 dialect: org.hibernate.dialect.MySQL5InnoDBDialect
小結
上面簡單總結了springboot下如何使用單元測試,關于單元測試更加詳細的介紹請參閱官方文檔: https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#boot-features-testing
參考資料 & 鳴謝
springboot官方文檔 https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#boot-features-testing
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。