亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

springboot使用單元測試實戰

2024-07-14 08:42:19
字體:
來源:轉載
供稿:網友

前言

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>

其中包含以下幾個庫:

  • Junit ——常用的單元測試庫
  • Spring Test & Spring Boot Test ——對Spring應用的集成測試支持
  • AssertJ——一個斷言庫
  • Hamcrest—— 一個匹配對象的庫
  • Mockito—— 一個Java模擬框架
  • JSONassert—— 一個針對JSON的斷言庫
  • JsonPath—— 用于JSON的XPath

下面我們將從Service層和Controller層的角度來簡單介紹下單元測試

Service單元測試

在SpringBoot 2.0中,創建一個Service的單元測試,代碼如下:

@RunWith(SpringRunner.class)@SpringBootTestpublic 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

  1. @RunWith : 該注解標簽是Junit提供的,用來說明此測試類的運行者,這里用了 SpringRunner ,它實際上繼承了 SpringJUnit4ClassRunner 類,而 SpringJUnit4ClassRunner 這個類是一個針對Junit 運行環境的自定義擴展,用來標準化在Springboot環境下Junit4.x的測試用例
  2. @SpringBootTest 為 springApplication創建上下文并支持SpringBoot特性

使用 @SpringBootTest 的 webEnvironment 屬性定義運行環境:

  1. Mock(默認) : 加載WebApplicationContext 并提供模擬的web環境 Servlet環境,使用此批注時,不會啟動嵌入式服務器
  2. RANDOM_PORT : 加載WebServerApplicationContext 并提供真實的web環境,嵌入式服務器, 監聽端口是隨機的
  3. DEFINED_PORT : 加載WebServerApplicationContext并提供真實的Web環境,嵌入式服務器啟動并監聽定義的端口(來自 application.properties或默認端口 8080)
  4. NONE : 使用SpringApplication加載ApplicationContext 但不提供任何Web環境

Controller的單元測試

首先創建一個Controller,代碼如下:

@RestControllerpublic 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@AutoConfigureMockMvcpublic 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 有以下幾個基本的方法:

  • perform : 執行一個RequestBuilder請求,會自動執行SpringMVC的流程并映射到相應的控制器執行處理。
  • andExpect: 添加RequsetMatcher驗證規則,驗證控制器執行完成后結果是否正確
  • andDo: 添加ResultHandler結果處理器,比如調試時打印結果到控制臺
  • andReturn: 最后返回相應的MvcResult,然后進行自定義驗證/進行下一步的異步處理

這里有一個小技巧,一般來說對于一個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@AutoConfigureMockMvcpublic 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)@SpringBootTestpublic 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 : MyISAM是MySQL5.5之前版本默認的數據庫存儲引擎,MyISAM提供高速存儲和檢索,以及全文搜索能力,適合數據倉庫等查詢頻繁的應用,但 不支持事務和外鍵,不能在表損壞后恢復數據
  • InnoDB : InnoDB是MySQL5.5版本的默認數據庫存儲引擎,InnoDB具有提交,回滾和崩潰恢復能力的事務安全, 支持事務和外鍵 ,比起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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲国产精品久久久久秋霞蜜臀| 成人在线视频网站| 欧美激情手机在线视频| 精品国产一区av| 中文字幕亚洲激情| 亚洲第一网中文字幕| 国产精品吊钟奶在线| 色偷偷噜噜噜亚洲男人| 8090理伦午夜在线电影| 精品少妇一区二区30p| 欧美激情网友自拍| 国产精品电影一区| 6080yy精品一区二区三区| 日日摸夜夜添一区| 欧美肥臀大乳一区二区免费视频| 欧美亚洲国产视频小说| 欧美怡红院视频一区二区三区| 亚洲欧美一区二区精品久久久| 亚洲第一福利网| 日本精品性网站在线观看| 亚洲裸体xxxx| 欧美乱妇40p| 91九色国产在线| 久热精品视频在线观看| 亚洲精品一区中文字幕乱码| 欧美丝袜第一区| 国产精品伦子伦免费视频| 久久久久久国产精品三级玉女聊斋| 久久久久日韩精品久久久男男| 欧美国产乱视频| 亚洲天堂开心观看| 尤物精品国产第一福利三区| 在线成人免费网站| 亚洲精品国产精品自产a区红杏吧| 亚洲午夜激情免费视频| 国产精品视频自拍| 日韩av在线网| 最近中文字幕mv在线一区二区三区四区| 亚洲一区国产精品| 精品久久国产精品| 国产精品主播视频| 日韩欧美视频一区二区三区| 欧美一性一乱一交一视频| 欧美成人精品三级在线观看| 精品自在线视频| 狠狠躁夜夜躁人人躁婷婷91| 亚洲午夜女主播在线直播| 91精品国产综合久久香蕉922| 欧美成人免费在线视频| 91在线网站视频| 97在线精品国自产拍中文| 福利二区91精品bt7086| 欧美日韩激情小视频| 91干在线观看| 成人a视频在线观看| 91精品国产成人| 欧美在线视频一区| 日本成人免费在线| 亚洲japanese制服美女| 欧美另类极品videosbestfree| 欧美亚洲另类激情另类| 欧美日韩国产激情| 隔壁老王国产在线精品| 亚州欧美日韩中文视频| 性欧美暴力猛交69hd| 91黑丝在线观看| 亚洲男女性事视频| 日韩一区二区三区国产| 久久伊人91精品综合网站| 日韩电影在线观看永久视频免费网站| 亚洲综合中文字幕在线观看| 91高清视频免费观看| 亚洲视频在线观看网站| 日韩电影中文字幕一区| 91精品国产91久久久| 亚洲一区二区久久久| 欧美极品少妇xxxxⅹ免费视频| 久久久亚洲国产天美传媒修理工| 亚洲美腿欧美激情另类| 久久国产精品久久精品| 国产成人精品综合久久久| 国产婷婷色综合av蜜臀av| 精品电影在线观看| 国产精品99久久久久久白浆小说| 国产一区二区三区欧美| 久久久久久亚洲| 亚洲视频999| 88国产精品欧美一区二区三区| 国产一区二区三区在线播放免费观看| 精品国模在线视频| 91社影院在线观看| 国产成人午夜视频网址| 亚洲国产精品大全| 6080yy精品一区二区三区| 日韩有码在线视频| 91色在线观看| 国产成人精品久久亚洲高清不卡| 亚洲自拍高清视频网站| 日韩高清a**址| 中文字幕v亚洲ⅴv天堂| 欧美一级片一区| 97成人精品视频在线观看| 久久影院资源网| 日韩一区二区三区国产| 亚洲精品第一国产综合精品| 4p变态网欧美系列| 亚洲香蕉成人av网站在线观看| 亚洲人成绝费网站色www| 性色av一区二区三区| 97国产精品人人爽人人做| 日韩在线精品一区| 欧美精品情趣视频| 日本午夜精品理论片a级appf发布| 亚洲免费av电影| 69久久夜色精品国产69| 国产噜噜噜噜噜久久久久久久久| 日本午夜在线亚洲.国产| 国产精品激情av电影在线观看| 国外色69视频在线观看| 成人精品视频久久久久| 欧美一级淫片丝袜脚交| 国产精品露脸自拍| 美女扒开尿口让男人操亚洲视频网站| 久久不射热爱视频精品| 亚洲最大中文字幕| 欧美日韩另类字幕中文| 不卡av电影在线观看| 最近2019年中文视频免费在线观看| 国产精品成人国产乱一区| 黑人巨大精品欧美一区二区一视频| 久久成人精品电影| 2020久久国产精品| 中文字幕亚洲欧美日韩在线不卡| 亚洲国产精品视频在线观看| 日韩精品视频在线播放| 不卡av电影在线观看| 亚洲人成网站色ww在线| 亚洲免费影视第一页| 在线观看中文字幕亚洲| 在线观看精品自拍私拍| 亚洲欧美国产精品专区久久| 久久精品国产亚洲精品| 国产精品久久久久久中文字| 国产日韩精品综合网站| 欧美一级淫片丝袜脚交| 国产精品视频99| 亚洲国产女人aaa毛片在线| 亚洲精品福利在线观看| 亚洲欧美日韩一区在线| 欧美国产日韩视频| 国产精品电影在线观看| 国产日韩欧美夫妻视频在线观看| 亚洲天堂男人天堂女人天堂| 久久人人爽人人爽爽久久| 中文字幕欧美日韩在线| 久久久国产一区二区三区| 国产精品日韩久久久久| 日韩中文在线中文网三级| 亚洲成avwww人| 欧美激情精品久久久久久变态| 欧美成年人在线观看| 91精品免费久久久久久久久| 九九热在线精品视频| 欧美成人精品h版在线观看|