最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot使用單元測試實戰(zhàn)

 更新時間:2018年09月10日 15:08:42   作者:pjmike_pj  
這篇文章主要介紹了springboot使用單元測試實戰(zhàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

前言

springboot提供了 spirng-boot-starter-test 以供開發(fā)者使用單元測試,在引入 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應(yīng)用的集成測試支持
  • AssertJ——一個斷言庫
  • Hamcrest—— 一個匹配對象的庫
  • Mockito—— 一個Java模擬框架
  • JSONassert—— 一個針對JSON的斷言庫
  • JsonPath—— 用于JSON的XPath

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

Service單元測試

在SpringBoot 2.0中,創(chuàng)建一個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

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

使用 @SpringBootTest 的 webEnvironment 屬性定義運行環(huán)境:

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

Controller的單元測試

首先創(chuàng)建一個Controller,代碼如下:

@RestController
public class UserController {
  @Autowired
  private UserService userService;
  @PostMapping("/user")
  public String userMapping(@RequestBody User user){
    userService.insertUser(user);
    return "ok";
  }
}

然后創(chuàng)建Controller的單元測試,一般有兩種創(chuàng)建方法。

第一種使用模擬環(huán)境進行測試

默認情況下,@SpringBootTest 不會啟動服務(wù)器,如果需針對此模擬環(huán)境測試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 有以下幾個基本的方法:

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

這里有一個小技巧,一般來說對于一個controller中往往有不止一個Request請求需要測試,敲打MockMvcRequestBuilders與MockMvcResultMatchers會顯得比較繁瑣,有一個簡便的方法就是將這兩個類的方法使用 import static 靜態(tài)導(dǎo)入,然后就可以直接使用兩個類的靜態(tài)方法了。然后代碼就變成如下所示:

...
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"));
  }
}

另外,如果是只想關(guān)注Web層而不是啟動完整的ApplicationContext,可以考慮使用 @WebMvcTest 注解,該注解不能與@SpringBootTest搭配使用,而且它只關(guān)注Web層面,至于涉及到數(shù)據(jù)層的時候,需要引入相關(guān)依賴,關(guān)于這個注解更多的介紹請參閱官方文檔: https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests

使用MockMvcBuilder構(gòu)建MockMvc對象

除了上面用 @AutoConfigureMockMvc 注解直接自動注入 MockMvc的方式,我們還可以利用MockMvcBuilder來構(gòu)建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環(huán)境進行測試

在@SpringBootTest注解中設(shè)置屬性 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("狀態(tài)碼: "+responseEntity.getStatusCodeValue());
  }
}

上面的代碼中有一個關(guān)鍵的類—— TestRestTemplate , TestRestTemplate是Spring的RestTemplate的一種替代品,可用于集成測試,更RestTemplate的使用功能方法類似,一般用于真實web環(huán)境測試中,關(guān)于該類更加詳細的用法參考官方文檔: https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#boot-features-test-scope-dependencies

單元測試回滾

單元測試的時候,如果不想造成垃圾數(shù)據(jù),可以開啟事務(wù)功能,在方法或類頭部添加 @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 注解,默認情況下在測試方法的末尾會回滾事務(wù)。然而有一些特殊情況需要注意,當(dāng)我們使用 RANDOM_PORT 或 DEFINED_PORT 這種安排隱式提供了一個真正的Servlet環(huán)境,所以HTTP客戶端和服務(wù)器將在不同的線程中運行,從而分離事務(wù),這種情況下,在服務(wù)器上啟動的任何事務(wù)都不會回滾。

當(dāng)然如果你想關(guān)閉回滾,只要加上 @Rollback(false) 注解即可, @Rollback 表示事務(wù)執(zhí)行完回滾,支持傳入一個value,默認true即回滾,false不回滾。

還有一種情況需要注意,就是如果你使用的數(shù)據(jù)庫是MySQL,有時候會發(fā)現(xiàn)加了注解 @Transactionl 也不會回滾,那么你就要查看一下你的默認引擎是不是InnoDB,如果不是就要改成 InnoDB。

MyISAM 與 InnoDB是mysql目前比較常用的兩個數(shù)據(jù)庫引擎,MyISAM與InnoDB的主要的不同點在于性能和事務(wù)控制上,這里簡單介紹下兩者的區(qū)別與轉(zhuǎn)換方法:

  • MyISAM : MyISAM是MySQL5.5之前版本默認的數(shù)據(jù)庫存儲引擎,MyISAM提供高速存儲和檢索,以及全文搜索能力,適合數(shù)據(jù)倉庫等查詢頻繁的應(yīng)用,但 不支持事務(wù)和外鍵,不能在表損壞后恢復(fù)數(shù)據(jù)
  • InnoDB : InnoDB是MySQL5.5版本的默認數(shù)據(jù)庫存儲引擎,InnoDB具有提交,回滾和崩潰恢復(fù)能力的事務(wù)安全, 支持事務(wù)和外鍵 ,比起MyISAM,InnoDB寫的處理效率差一些并且會占用更多的磁盤空間以保留數(shù)據(jù)和索引。

如果你的數(shù)據(jù)表是MyISAM引擎,由于它不支持事務(wù),在單元測試中添加事務(wù)注解,測試方法也是不會回滾的。

修改默認引擎

查看MySQL當(dāng)前默認的存儲引擎

mysql> show variables like '%storage_engine%';

看具體的表user表用了什么引擎(engine后面的就表示當(dāng)前表的存儲引擎)

mysql> show create table user;

將user表修為InnoDB存儲引擎

mysql> ALTER TABLE user ENGINE=INNODB;

注意

這里還有一點需要注意的地方, 當(dāng)我們使用Spring Data JPA時,如果沒有指定MySQL建表時的存儲引擎,默認情況下會使用MySQL的MyISAM ,這也是一個坑點,這種情況下,你在單元測試使用 @Transactional 注解,回滾不會起作用。

解決方法是將 hibernate.dialect 屬性配置成 hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect ,指定MySQL建表的時候使用 InnoDB引擎,示例配置文件如下:

spring:
 jpa:
  # 數(shù)據(jù)庫類型
  database: mysql
  # 輸出日志
  show-sql: true
  properties:
   hibernate:
    # JPA配置
    hbm2ddl.auto: update
    # mysql存儲類型配置
    dialect: org.hibernate.dialect.MySQL5InnoDBDialect

小結(jié)

上面簡單總結(jié)了springboot下如何使用單元測試,關(guān)于單元測試更加詳細的介紹請參閱官方文檔: 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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 使用Jackson進行JSON生成與解析的新手指南

    使用Jackson進行JSON生成與解析的新手指南

    這篇文章主要為大家詳細介紹了如何使用Jackson進行JSON生成與解析處理,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-04-04
  • mybatisplus?復(fù)合主鍵(多主鍵)?CRUD示例詳解

    mybatisplus?復(fù)合主鍵(多主鍵)?CRUD示例詳解

    這篇文章主要介紹了mybatisplus?復(fù)合主鍵(多主鍵)?CRUD實例詳解,本文通過實例代碼圖文相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • SpringBoot詳解如何實現(xiàn)讀寫分離

    SpringBoot詳解如何實現(xiàn)讀寫分離

    當(dāng)響應(yīng)的瓶頸在數(shù)據(jù)庫的時候,就要考慮數(shù)據(jù)庫的讀寫分離,當(dāng)然還可以分庫分表,那是單表數(shù)據(jù)量特別大,當(dāng)單表數(shù)據(jù)量不是特別大,但是請求量比較大的時候,就要考慮讀寫分離了.具體的話,還是要看自己的業(yè)務(wù)...如果還是很慢,那就要分庫分表了...我們這篇就簡單講一下讀寫分離
    2022-05-05
  • Spring中@Autowired、@Qualifier、@Resource注解的區(qū)別

    Spring中@Autowired、@Qualifier、@Resource注解的區(qū)別

    這篇文章主要介紹了Spring中@Autowired、@Qualifier、@Resource注解的區(qū)別,@Autowired 可以單獨使用,如果單獨使用,它將按類型裝配,因此,如果在容器中聲明了多個相同類型的bean,則會出現(xiàn)問題,因為 @Autowired 不知道要使用哪個bean來注入,需要的朋友可以參考下
    2023-11-11
  • springboot 微信授權(quán)網(wǎng)頁登錄操作流程

    springboot 微信授權(quán)網(wǎng)頁登錄操作流程

    這篇文章主要介紹了springboot 微信授權(quán)網(wǎng)頁登錄操作流程,本文通過實例圖文相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • 徹底搞定堆排序:二叉堆

    徹底搞定堆排序:二叉堆

    二叉堆有兩種:最大堆和最小堆。最大堆:父結(jié)點的鍵值總是大于或等于任何一個子節(jié)點的鍵值;最小堆:父結(jié)點的鍵值總是小于或等于任何一個子節(jié)點的鍵值
    2021-07-07
  • Spring中TransactionSynchronizationManager的使用詳解

    Spring中TransactionSynchronizationManager的使用詳解

    這篇文章主要介紹了Spring中TransactionSynchronizationManager的使用詳解,TransactionSynchronizationManager是事務(wù)同步管理器,監(jiān)聽事務(wù)的操作,來實現(xiàn)在事務(wù)前后可以添加一些指定操作,需要的朋友可以參考下
    2023-09-09
  • 淺談一下SpringBoot中的異步任務(wù)

    淺談一下SpringBoot中的異步任務(wù)

    這篇文章主要介紹了淺談一下SpringBoot中的異步任務(wù),SpringBoot 中的異步任務(wù)主要是指在 SpringBoot 中使用異步線程完成處理任務(wù),在 SpringBoot 中使用異步線程非常簡單,只需要兩個注解就可以搞定,需要的朋友可以參考下
    2023-10-10
  • Java字符串無意識的遞歸過程解析

    Java字符串無意識的遞歸過程解析

    這篇文章主要介紹了Java字符串無意識的遞歸過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • Springboot項目引入druid安裝部署使用教程

    Springboot項目引入druid安裝部署使用教程

    這篇文章主要介紹了Springboot項目引入druid安裝部署使用,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01

最新評論

安泽县| 黄平县| 柞水县| 景洪市| 吕梁市| 连城县| 柏乡县| 宣恩县| 宝鸡市| 宜昌市| 邵武市| 满洲里市| 宁津县| 桂平市| 莱阳市| 襄汾县| 呼玛县| 于都县| 化德县| 陵水| 日喀则市| 成都市| 尚义县| 金川县| 那曲县| 宁波市| 二连浩特市| 宁德市| 资兴市| 会宁县| 北辰区| 铅山县| 济南市| 莱西市| 驻马店市| 永昌县| 东乡县| 温泉县| 满洲里市| 新巴尔虎左旗| 昭苏县|