前面寫了這麼多章節,都是經過瀏覽器訪問的形式,進行接口方法訪問進而驗證方法的正確與否。顯然在服務或者接口比較少時,這麼作沒有啥問題,但一旦一個項目稍微複雜或者接口方法比較多時,這麼驗證就有點不符合程序猿的
懶人
的特性了。因此這章節,講述下SpringBoot
中的單元測試及基於Contiperf
壓測工具進行性能測試相關方面的知識點。html
是指對軟件中的最小可
測試單元
進行檢查和驗證。通常上在開發階段或者程序發佈時,都會利用像Maven
這樣的打包工具進行打包前的測試,避免沒必要要的bug程序被打包部署。java
題外話:在開發階段,都應該要求編寫單元測試,核心的模塊還須要進行覆蓋測試,覆蓋率至少要95%以上。git
對於
java
開發者而言,Junit
應該無人不知了。因此SpringBoot
也是基於Junit
進行單位測試的。github
0.加入pom依賴。web
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
1.這裏爲了演示,編寫了一個簡單的測試接口及編寫對應的測試類。spring
UnitTestService.javaapi
/** * 測試接口類 * @author oKong * */ public interface UnitTestService { public String process(String msg); }
實現類:UnitTestServiceImpl.java瀏覽器
@Service public class UnitTestServiceImpl implements UnitTestService{ /** * 爲了測試,這裏直接返回傳入的值 */ @Override public String process(String msg) { // TODO Auto-generated method stub return msg; } }
測試類:UnitTestServiceTest.javaspringboot
題外話:我的建議,每一個測試類都應該和對應的被測試類包路徑一致。同時測試類的名稱是被測試的類名+Test,如本例所示的:微信
/** * 編寫接口測試類 * @author oKong * */ @RunWith(SpringRunner.class) //SpringBootTest 是springboot 用於測試的註解,可指定啓動類或者測試環境等,這裏直接默認。 @SpringBootTest public class UnitTestServiceTest { @Autowired UnitTestService testService; public void test() { String msg = "this is a test"; String result = testService.process(msg); //斷言 是否和預期一致 Assert.assertEquals(msg, result); } }
run As
--> Junit Test
或者須要debug時,選擇Debug As
--> Junit Test
,運行便可。3.至此,一個簡單的單元測試就結束了。**簡單來講,寫一個單元測試是容易的,但寫好一個單元測試是難的。**畢竟,每一個程序猿都以爲本身的代碼是沒有問題的,難道不是嗎?哈哈!
對於服務類而言,編寫單元測試是相對簡單的,只須要像控制層自動引入接口類同樣。但編寫控制層即RESTful API 單元測試時,通常上就須要利用
Mock
技術進行測試了。固然也可使用像Swagger
或者PostMan
這樣的api測試工具進行測試(或者使用RestTemplate
測試也是可行的),它可進行自動化測試,關於Postman
會在以後的章節進行更新,做者也沒有過多研究過,也只是用到了它的最基本的發起http請求的功能,以後會整理相關資料的。
0.建立一個RESTful接口服務。
/** * 編寫mock測試服務 * @author oKong * */ @RestController public class DemoController { @GetMapping("/mock") public String demo(String msg) { return msg; } }
1.編寫對應測試類
@RunWith(SpringRunner.class) //SpringBootTest 是springboot 用於測試的註解,可指定啓動類或者測試環境等,這裏直接默認。 //由於是mock測試,在實際開發過程當中,可指定其測試啓動時爲隨機端口,避免了沒必要要的端口衝突。 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) //測試單一接口時 ,也可利用註解@WebMvcTest 進行單一測試 //@WebMvcTest(DemoController.class) public class DemoControllerTest { //使用 WebMvcTest 時使用 //@autowired mockMvc 是可自動注入的。 //當直接使用SpringBootTest 會提示 注入失敗 這裏直接示例利用 MockMvcBuilders工具建立 //@Autowired MockMvc mockMvc; @Autowired WebApplicationContext wc; @Before public void beforeSetUp() { this.mockMvc = MockMvcBuilders.webAppContextSetup(wc).build(); } @Test public void testDemo() throws Exception { String msg = "this is a mock test"; MvcResult result = this.mockMvc.perform(get("/mock").param("msg", msg)).andDo(print()).andExpect(status().isOk()) .andReturn(); //斷言 是否和預期相等 Assert.assertEquals(msg, result.getResponse().getContentAsString()); } }
2.運行右擊,選擇 run As
--> Junit Test
或者須要debug時,選擇Debug As
--> Junit Test
,運行便可。(也能夠看見每次啓動測試時,每次端口號都是不一樣的。)
2018-07-25 23:16:28.733 INFO 13000 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 59999 (http) 2018-07-25 23:16:28.754 INFO 13000 --- [ main] c.l.l.s.c.controller.DemoControllerTest : Started DemoControllerTest in 5.673 seconds (JVM running for 6.769)
因爲配置了print()
這個ResultHandler
,因此控制檯會打印相關參數信息。建議設置此屬性,這樣就算測試有問題,也能看下具體的參數信息。其餘相關mock的用法,此處就不舉例了,你們可自行搜索下,比較本章節只是簡單示例下用法~
MockMvc
對象,故可建立一個基類,這樣免得每次都寫。BaseMockTest.java
/** * mock 基類 * @author oKong * */ public abstract class BaseMockTest { @Autowired private WebApplicationContext wc; protected MockMvc mockMvc; @Before public void beforeSetUp() { this.mockMvc = MockMvcBuilders.webAppContextSetup(wc).build(); } }
這樣編寫mock測試類時,還須要繼承此基類便可。
詳細的使用,你們可自行谷歌下,畢竟經常使用的也就前面三個了,(┬_┬)
ContiPerf是一個輕量級的測試工具,基於JUnit 4 開發,可用於效率測試等。能夠指定在線程數量和執行次數,經過限制最大時間和平均執行時間來進行性能測試。
0.加入pom依賴包。
<dependency> <groupId>org.databene</groupId> <artifactId>contiperf</artifactId> <version>2.3.4</version> <scope>test</scope> </dependency>
1.改寫UnitTestServiceTest
測試類,進入ContiPerfRule
。 題外話:@Rule
是Junit
提供的一個擴展接口註解,其接口類爲:org.junit.rules.MethodRule
,注意在Junit5中,已經被TestRule
因此替代了。這裏只是簡單提下,由於具體的也不是很清楚,也沒有深刻了解過。
/** * 編寫接口測試類 * @author oKong * */ @RunWith(SpringRunner.class) //SpringBootTest 是springboot 用於測試的註解,可指定啓動類或者測試環境等,這裏直接默認。 @SpringBootTest public class UnitTestServiceTest { @Autowired UnitTestService testService; //引入 ContiPerf 進行性能測試 @Rule public ContiPerfRule contiPerfRule = new ContiPerfRule(); @Test //10個線程 執行10次 @PerfTest(invocations = 100,threads = 10) public void test() { String msg = "this is a test"; String result = testService.process(msg); //斷言 是否和預期一致 Assert.assertEquals(msg, result); } }
target/contiperf-report/index.html
,會有圖表提示。控制檯輸出:
cn.lqdev.learning.springboot.chapter13.service.UnitTestServiceTest.test samples: 100 max: 403 average: 41.5 median: 15
測試報告:
@PerfTest
@Required
本章節主要是對
Junit
和ContiPerf
的使用簡單的示例,像MockMvc
的詳細用法並無深刻,你們可自行搜索下,畢竟我也用的很少呀。
目前互聯網上不少大佬都有
SpringBoot
系列教程,若有雷同,請多多包涵了。本文是做者在電腦前一字一句敲的,每一步都是實踐的。若文中有所錯誤之處,還望提出,謝謝。
499452441
lqdevOps
完整示例:chapter-13