Spring Boot 提供了豐富的測(cè)試功能,主要由以下兩個(gè)模塊組成:
-
spring-boot-test
:提供測(cè)試核心功能。 -
spring-boot-test-autoconfigure
:提供對(duì)測(cè)試的自動(dòng)配置。
Spring Boot 提供了一個(gè)?spring-boot-starter-test
一站式啟動(dòng)器,如以下依賴配置所示。
<dependency>
?<groupId>org.springframework.boot</groupId>
?<artifactId>spring-boot-starter-test</artifactId>
?<scope>test</scope>
</dependency>
測(cè)試啟動(dòng)器依賴不僅包含以上兩個(gè) Spring Boot模塊,還包含 Spring Test 測(cè)試模塊,以及其他
第三方測(cè)試類庫,如下所示。
-
JUnit 5:Java 最主流的單元測(cè)試框架。
-
AssertJ:一款快速斷言庫。
-
Hamcrest:一款單元測(cè)試匹配庫。
-
Mockito:一款 Mock 測(cè)試框架。
-
JSONassert:一款 JSON 斷言庫。
-
JsonPath:一款 JSON XPath 庫。
更多測(cè)試相關(guān)的依賴可見具體的依賴關(guān)系樹,如下圖所示。
以上這些都是 Spring Boot 提供的常用的測(cè)試類庫,如果上面的測(cè)試類庫還不能滿足你的需要,也可以任意添加以上沒有的類庫。
現(xiàn)在基本上使用的是 JUnit 5,如果應(yīng)用還在使用JUnit 4 寫的單元測(cè)試用例,那么也可以使用JUnit 5 的 Vintage 引擎來運(yùn)行,如下面的依賴配置所示。
<dependency>
?<groupId>org.junit.vintage</groupId>
?<artifactId>junit-vintage-engine</artifactId>
?<scope>test</scope>
?<exclusions>
?<exclusion>
?<groupId>org.hamcrest</groupId>
?<artifactId>hamcrest-core</artifactId>
?</exclusion>
?</exclusions>
</dependency>
需要排除?hamcrest-core
?依賴,因?yàn)樵撘蕾囈呀?jīng)改坐標(biāo)了,并且默認(rèn)內(nèi)置在Spring Boot依賴管理中,如上面的依賴關(guān)系樹所示,最新的 Hamcrest依賴已經(jīng)是org.hamcrest:hamcrest
坐標(biāo)了。
Spring Boot提供了一個(gè)?@SpringBootTest
?注解,用在單元測(cè)試類上以啟用支持Spring Boot特性的單元測(cè)試,如果使用的是JUnit 4,那么測(cè)試類上還需要額外的@RunWith(SpringRunner. class)
注解,然后在測(cè)試類方法上添加?@Test
?注解即可,每一個(gè)?@Test
?注解修飾的方法就是一個(gè)單元測(cè)試方法。
@SpringBootTest
?注解有一個(gè)最重要的?webEnvironment
?環(huán)境參數(shù),支持以下幾種環(huán)境設(shè)置:
-
MOCK(默認(rèn)):?加載一個(gè)?
Web ApplicationContext
?并提供一個(gè)?Mock Web Environment
,但不會(huì)啟動(dòng)內(nèi)嵌的 Web 服務(wù)器,并可以結(jié)合?@AutoConfifigureMockMvcor
?和?@AutoConfifigure-WebTestClient
?注解一起使用進(jìn)行 Mock 測(cè)試。 -
RANDOM_PORT:?加載一個(gè)?
WebServerApplicationContext
,以及提供一個(gè)真實(shí)的?WebEnvironment
,并以隨機(jī)端口啟動(dòng)內(nèi)嵌服務(wù)器。 -
DEFINED_PORT:?和?
RANDOM_PORT
?一樣,不同的是?DEFINED_PORT
?是以應(yīng)用指定的端口運(yùn)行的,默認(rèn)端口為 8080。 -
NONE:?加載一個(gè)?
ApplicationContext
,但不會(huì)提供任何?Web Environment
。
如果使用的?@SpringBootTest
?注解不帶任何參數(shù),則默認(rèn)為 Mock 環(huán)境。
真實(shí)環(huán)境測(cè)試
在?@SpringBootTest
?注解中指定基于隨機(jī)端口的真實(shí)Web環(huán)境,然后在類成員變量或者方法參數(shù)上注入?TestRestTemplate
?實(shí)例,就可以完成對(duì) Spring MVC接口的真實(shí)環(huán)境測(cè)試。
下面是一個(gè)基于隨機(jī)端口的真實(shí)環(huán)境的測(cè)試用例:
@SpringBootTest(webEnvironment?=?SpringBootTest.WebEnvironment.RANDOM_PORT)
public?class?MvcTest?{
?@Test
?public?void?getUserTest(@Autowired?TestRestTemplate?testRestTemplate)?{
?Map<String,?String>?multiValueMap?=?new?HashMap<>();
?multiValueMap.put("username",?"Java?技術(shù)棧?");
?Result?result?=?testRestTemplate.getForObject("/user/get?username={username}",
?Result.class,?multiValueMap);
?assertThat(result.getCode()).isEqualTo(0);
?assertThat(result.getMsg()).isEqualTo("ok");
?}
?
}
測(cè)試當(dāng)前應(yīng)用下的?/user/get
?接口,傳入對(duì)應(yīng)的用戶名參數(shù),最后檢查接口返回結(jié)果是否和預(yù)期一致,測(cè)試結(jié)果如下圖所示。
單元測(cè)試通過,從執(zhí)行日志可以看到,它啟動(dòng)了一個(gè)嵌入式的 Tomcat 容器來測(cè)試真實(shí)的 Web應(yīng)用環(huán)境。
Mock 環(huán)境測(cè)試
通過在類上面使用?@AutoConfifigureMockMvc
?注解,然后在類成員變量或者方法參數(shù)上注入MockMvc 實(shí)例,就可以完成對(duì) Spring MVC 接口的 Mock 測(cè)試。
下面是一個(gè)基于默認(rèn) Mock 環(huán)境的測(cè)試用例:
@SpringBootTest
@AutoConfigureMockMvc
class?MockMvcTests?{
?@Test
?public?void?getUserTest(@Autowired?MockMvc?mvc)?throws?Exception?{
?mvc.perform(MockMvcRequestBuilders.get("/user/get?username={username}",?"test"))
?.andExpect(status().isOk())
?.andExpect(content().string("{\"code\":0,\"msg\":\"ok\",\"
data\":\"test\"}"));
?}
}
測(cè)試當(dāng)前應(yīng)用下的?/user/get
?接口,傳入對(duì)應(yīng)的用戶名參數(shù),最后檢查請(qǐng)求狀態(tài)是否OK(200),響應(yīng)的內(nèi)容是否和預(yù)期一致,測(cè)試結(jié)果如下圖所示。
單元測(cè)試通過,從執(zhí)行日志可以看到,它并未啟動(dòng)真實(shí)的 Web 環(huán)境來測(cè)試,而是使用 Mock 環(huán)境測(cè)試的。
Mock 組件測(cè)試
某些時(shí)候可能還需要模擬一些組件,比如某些服務(wù)只有上線之后才能調(diào)用,在開發(fā)階段不可用,這時(shí)就需要 Mock 模擬測(cè)試了,提供各種模擬組件以完成測(cè)試。
Spring Boot 提供了一個(gè)?@MockBean?
注解,可為 Spring 中的 Bean 組件定義基于 Mockito 的Mock 測(cè)試,它可以創(chuàng)建一個(gè)新 Bean 以覆蓋 Spring 環(huán)境中已有的 Bean,它可以用在測(cè)試類、成員變量上,或者?@Confifiguration
?配置類、成員變量上,被模擬的 Bean 在每次測(cè)試結(jié)束后自動(dòng)重置。
假現(xiàn)現(xiàn)在有一個(gè)遠(yuǎn)程的服務(wù)?userService
,本地不能調(diào)用,現(xiàn)在進(jìn)行 Mock 測(cè)試,如以下使用示例所示。
@SpringBootTest
class?MockBeanTests?{
//?@Autowired
//?private?UserService?userService;
?@MockBean
?private?UserService?userService;
?@Test
?public?void?countAllUsers()?{
?BDDMockito.given(this.userService.countAllUsers()).willReturn(88);
?assertThat(this.userService.countAllUsers()).isEqualTo(88);
?}
}
這里的?@MockBean
?注解使用在 UserService 變量上,表明這個(gè)userService
實(shí)例在當(dāng)前測(cè)試用例中是被 Mock 覆蓋的,如果要模擬的 Bean 有多個(gè),則可以使用@Qualififier
注解指定,然后通過Mockito 提供的代理工具類方法創(chuàng)建模擬返回?cái)?shù)據(jù),運(yùn)行該服務(wù)的測(cè)試方法,當(dāng)模擬數(shù)據(jù)和預(yù)期結(jié)果一致時(shí)才會(huì)測(cè)試通過。
這里通過?BDDMockito
?工具類模擬?userService#countAllUsers
方法并讓它返回統(tǒng)計(jì)的用戶總數(shù)(88),最后檢查該方法的返回值是否和預(yù)期一致,測(cè)試結(jié)果如下圖所示。
單元測(cè)試通過,也可以使用?@SpyBean
?注解代替?@MockBean
?注解,兩者的區(qū)別是:
-
@SpyBean
—如果沒有提供 Mockito 代理方法,則會(huì)調(diào)用真實(shí)的 Bean 來獲取數(shù)據(jù)。 -
@MockBean
—不管有沒有提供 Mockito 代理方法,都會(huì)調(diào)用 Mock 的 Bean 來獲取數(shù)據(jù)。文章來源:http://www.zghlxwxcb.cn/news/detail-764704.html
@MockBean
、@SpyBean
?注解既可作用于 Mock 環(huán)境,也可作用于真實(shí)環(huán)境,它只是用來模擬、替換環(huán)境中指定的 Bean 而已,但不能用于模擬在應(yīng)用上下文刷新期間 Bean 的行為,因?yàn)樵趫?zhí)行測(cè)試用例時(shí)應(yīng)用上下文已經(jīng)刷新完成了,所以不可能再去模擬了,這種情況下建議使用?@Bean
?方法來創(chuàng)建模擬配置。文章來源地址http://www.zghlxwxcb.cn/news/detail-764704.html
到了這里,關(guān)于Spring Boot 做單元測(cè)試,真心強(qiáng)悍!的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!