欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

springboot使用單元測(cè)試實(shí)戰(zhàn)

前言

10年的太原網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都全網(wǎng)營(yíng)銷(xiāo)的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整太原建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)建站從事“太原網(wǎng)站設(shè)計(jì)”,“太原網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

springboot提供了 spirng-boot-starter-test 以供開(kāi)發(fā)者使用單元測(cè)試,在引入 spring-boot-starter-test 依賴后:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

其中包含以下幾個(gè)庫(kù):

  • Junit ——常用的單元測(cè)試庫(kù)
  • Spring Test & Spring Boot Test ——對(duì)Spring應(yīng)用的集成測(cè)試支持
  • AssertJ——一個(gè)斷言庫(kù)
  • Hamcrest—— 一個(gè)匹配對(duì)象的庫(kù)
  • Mockito—— 一個(gè)Java模擬框架
  • JSONassert—— 一個(gè)針對(duì)JSON的斷言庫(kù)
  • JsonPath—— 用于JSON的XPath

下面我們將從Service層和Controller層的角度來(lái)簡(jiǎn)單介紹下單元測(cè)試

Service單元測(cè)試

在SpringBoot 2.0中,創(chuàng)建一個(gè)Service的單元測(cè)試,代碼如下:

@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);
  }
}

上面的測(cè)試非常簡(jiǎn)單,主要需要注意兩個(gè)注解: @RunWith 和 @SpringBootTest

  1. @RunWith : 該注解標(biāo)簽是Junit提供的,用來(lái)說(shuō)明此測(cè)試類(lèi)的運(yùn)行者,這里用了 SpringRunner ,它實(shí)際上繼承了 SpringJUnit4ClassRunner 類(lèi),而 SpringJUnit4ClassRunner 這個(gè)類(lèi)是一個(gè)針對(duì)Junit 運(yùn)行環(huán)境的自定義擴(kuò)展,用來(lái)標(biāo)準(zhǔn)化在Springboot環(huán)境下Junit4.x的測(cè)試用例
  2. @SpringBootTest 為 springApplication創(chuàng)建上下文并支持SpringBoot特性

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

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

Controller的單元測(cè)試

首先創(chuàng)建一個(gè)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的單元測(cè)試,一般有兩種創(chuàng)建方法。

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

默認(rèn)情況下,@SpringBootTest 不會(huì)啟動(dòng)服務(wù)器,如果需針對(duì)此模擬環(huán)境測(cè)試Web端點(diǎn),可以如下配置 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"));
  }
}

這里有一個(gè) @AutoConfigureMockMvc 注解,該注解表示啟動(dòng)測(cè)試的時(shí)候自動(dòng)注入 MockMvc ,而這個(gè) MockMvc 有以下幾個(gè)基本的方法:

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

這里有一個(gè)小技巧,一般來(lái)說(shuō)對(duì)于一個(gè)controller中往往有不止一個(gè)Request請(qǐng)求需要測(cè)試,敲打MockMvcRequestBuilders與MockMvcResultMatchers會(huì)顯得比較繁瑣,有一個(gè)簡(jiǎn)便的方法就是將這兩個(gè)類(lèi)的方法使用 import static 靜態(tài)導(dǎo)入,然后就可以直接使用兩個(gè)類(lèi)的靜態(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層而不是啟動(dòng)完整的ApplicationContext,可以考慮使用 @WebMvcTest 注解,該注解不能與@SpringBootTest搭配使用,而且它只關(guān)注Web層面,至于涉及到數(shù)據(jù)層的時(shí)候,需要引入相關(guān)依賴,關(guān)于這個(gè)注解更多的介紹請(qǐng)參閱官方文檔: 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對(duì)象

除了上面用 @AutoConfigureMockMvc 注解直接自動(dòng)注入 MockMvc的方式,我們還可以利用MockMvcBuilder來(lái)構(gòu)建MockMvc對(duì)象,示例代碼如下:

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

第二種使用真實(shí)Web環(huán)境進(jìn)行測(cè)試

在@SpringBootTest注解中設(shè)置屬性 webEnvironment = WebEnvironment.RANDOM_PORT ,每次運(yùn)行的時(shí)候會(huì)隨機(jī)選擇一個(gè)可用端口。我們也可以還使用 @LoalServerPort 注解用于本地端口號(hào)。下面是測(cè)試代碼:

@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());
  }
}

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

單元測(cè)試回滾

單元測(cè)試的時(shí)候,如果不想造成垃圾數(shù)據(jù),可以開(kāi)啟事務(wù)功能,在方法或類(lèi)頭部添加 @Transactional 注解即可,在官方文檔中對(duì)此也有說(shuō)明:

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

解讀一下,在單元測(cè)試中使用 @Transactional 注解,默認(rèn)情況下在測(cè)試方法的末尾會(huì)回滾事務(wù)。然而有一些特殊情況需要注意,當(dāng)我們使用 RANDOM_PORT 或 DEFINED_PORT 這種安排隱式提供了一個(gè)真正的Servlet環(huán)境,所以HTTP客戶端和服務(wù)器將在不同的線程中運(yùn)行,從而分離事務(wù),這種情況下,在服務(wù)器上啟動(dòng)的任何事務(wù)都不會(huì)回滾。

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

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

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

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

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

修改默認(rèn)引擎

查看MySQL當(dāng)前默認(rèn)的存儲(chǔ)引擎

mysql> show variables like '%storage_engine%';

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

mysql> show create table user;

將user表修為InnoDB存儲(chǔ)引擎

mysql> ALTER TABLE user ENGINE=INNODB;

注意

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

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

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

小結(jié)

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

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

本文名稱:springboot使用單元測(cè)試實(shí)戰(zhàn)
文章地址:http://www.chinadenli.net/article12/gisggc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站網(wǎng)站改版軟件開(kāi)發(fā)網(wǎng)站設(shè)計(jì)公司做網(wǎng)站靜態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化