中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

SpringBoot | 第十三章:測(cè)試相關(guān)(單元測(cè)試、性能測(cè)試)

2018-08-28    來(lái)源:importnew

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

前言

前面寫了這么多章節(jié),都是通過(guò)瀏覽器訪問(wèn)的形式,進(jìn)行接口方法訪問(wèn)進(jìn)而驗(yàn)證方法的正確與否。顯然在服務(wù)或者接口比較少時(shí),這么做沒有啥問(wèn)題,但一旦一個(gè)項(xiàng)目稍微復(fù)雜或者接口方法比較多時(shí),這么驗(yàn)證就有點(diǎn)不符合程序猿的懶人的特性了。所以這章節(jié),講述下SpringBoot中的單元測(cè)試及基于Contiperf壓測(cè)工具進(jìn)行性能測(cè)試相關(guān)方面的知識(shí)點(diǎn)。

單元測(cè)試

是指對(duì)軟件中的最小可測(cè)試單元進(jìn)行檢查和驗(yàn)證。一般上在開發(fā)階段或者程序發(fā)布時(shí),都會(huì)利用像Maven這樣的打包工具進(jìn)行打包前的測(cè)試,避免不必要的bug程序被打包部署。

題外話:在開發(fā)階段,都應(yīng)該要求編寫單元測(cè)試,核心的模塊還需要進(jìn)行覆蓋測(cè)試,覆蓋率至少要95%以上。

SpringBoot的單元測(cè)試

對(duì)于java開發(fā)者而言,Junit應(yīng)該無(wú)人不知了。所以SpringBoot也是基于Junit進(jìn)行單位測(cè)試的。

0.加入pom依賴。

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

1.這里為了演示,編寫了一個(gè)簡(jiǎn)單的測(cè)試接口及編寫對(duì)應(yīng)的測(cè)試類。

UnitTestService.java

/**
 * 測(cè)試接口類
 * @author oKong
 *
 */
public interface UnitTestService {
    
    public String process(String msg);

}

實(shí)現(xiàn)類:UnitTestServiceImpl.java

@Service
public class UnitTestServiceImpl implements UnitTestService{

    /**
     * 為了測(cè)試,這里直接返回傳入的值
     */
    @Override
    public String process(String msg) {
        // TODO Auto-generated method stub
        return msg;
    }
}

測(cè)試類:UnitTestServiceTest.java

題外話:個(gè)人建議,每個(gè)測(cè)試類都應(yīng)該和對(duì)應(yīng)的被測(cè)試類包路徑一致。同時(shí)測(cè)試類的名稱是被測(cè)試的類名+Test,如本例所示的:

示例

/**
 * 編寫接口測(cè)試類
 * @author oKong
 *
 */
@RunWith(SpringRunner.class)
//SpringBootTest 是springboot 用于測(cè)試的注解,可指定啟動(dòng)類或者測(cè)試環(huán)境等,這里直接默認(rèn)。
@SpringBootTest 
public class UnitTestServiceTest {
    
    @Autowired
    UnitTestService testService;
    
    public void test() {
        String msg = "this is a test";
        String result = testService.process(msg);
        //斷言 是否和預(yù)期一致
        Assert.assertEquals(msg, result);
    }
}

 

  1. 運(yùn)行右擊,選擇?run As?–>?Junit Test?或者需要debug時(shí),選擇Debug As?–>?Junit Test,運(yùn)行即可。

測(cè)試結(jié)果

3.至此,一個(gè)簡(jiǎn)單的單元測(cè)試就結(jié)束了。簡(jiǎn)單來(lái)說(shuō),寫一個(gè)單元測(cè)試是容易的,但寫好一個(gè)單元測(cè)試是難的。畢竟,每個(gè)程序猿都覺得自己的代碼是沒有問(wèn)題的,難道不是嗎?哈哈!

RESTful API 單元測(cè)試

對(duì)于服務(wù)類而言,編寫單元測(cè)試是相對(duì)簡(jiǎn)單的,只需要像控制層自動(dòng)引入接口類一樣。但編寫控制層即RESTful API 單元測(cè)試時(shí),一般上就需要利用Mock技術(shù)進(jìn)行測(cè)試了。當(dāng)然也可以使用像Swagger或者PostMan這樣的api測(cè)試工具進(jìn)行測(cè)試(或者使用RestTemplate測(cè)試也是可行的),它可進(jìn)行自動(dòng)化測(cè)試,關(guān)于Postman會(huì)在之后的章節(jié)進(jìn)行更新,作者也沒有過(guò)多研究過(guò),也只是用到了它的最基本的發(fā)起http請(qǐng)求的功能,之后會(huì)整理相關(guān)資料的。

0.創(chuàng)建一個(gè)RESTful接口服務(wù)。

/**
 * 編寫mock測(cè)試服務(wù)
 * @author oKong
 *
 */
@RestController
public class DemoController {

    @GetMapping("/mock")
    public String demo(String msg) {
        return msg;
    }
}

1.編寫對(duì)應(yīng)測(cè)試類

@RunWith(SpringRunner.class)
//SpringBootTest 是springboot 用于測(cè)試的注解,可指定啟動(dòng)類或者測(cè)試環(huán)境等,這里直接默認(rèn)。
//因?yàn)槭莔ock測(cè)試,在實(shí)際開發(fā)過(guò)程中,可指定其測(cè)試啟動(dòng)時(shí)為隨機(jī)端口,避免了不必要的端口沖突。
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) 
//測(cè)試單一接口時(shí) ,也可利用注解@WebMvcTest 進(jìn)行單一測(cè)試
//@WebMvcTest(DemoController.class)
public class DemoControllerTest {

    //使用 WebMvcTest 時(shí)使用 
    //@autowired mockMvc 是可自動(dòng)注入的。
    //當(dāng)直接使用SpringBootTest 會(huì)提示 注入失敗  這里直接示例利用 MockMvcBuilders工具創(chuàng)建
    //@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();
        
        //斷言 是否和預(yù)期相等
        Assert.assertEquals(msg, result.getResponse().getContentAsString());

    }
}

2.運(yùn)行右擊,選擇?run As?–>?Junit Test?或者需要debug時(shí),選擇Debug As?–>?Junit Test,運(yùn)行即可。(也可以看見每次啟動(dòng)測(cè)試時(shí),每次端口號(hào)都是不同的。)

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)

測(cè)試結(jié)果

由于配置了print()這個(gè)ResultHandler,所以控制臺(tái)會(huì)打印相關(guān)參數(shù)信息。建議設(shè)置此屬性,這樣就算測(cè)試有問(wèn)題,也能看下具體的參數(shù)信息。其他相關(guān)mock的用法,此處就不舉例了,大家可自行搜索下,比較本章節(jié)只是簡(jiǎn)單示例下用法~

請(qǐng)求參數(shù)信息

  1. 鑒于每次編寫控制層測(cè)試類時(shí),都需要?jiǎng)?chuàng)建MockMvc對(duì)象,故可創(chuàng)建一個(gè)基類,這樣省得每次都寫。

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測(cè)試類時(shí),還需要繼承此基類即可。

Junit常用注解說(shuō)明

  • @Test 加在待測(cè)試的方法前面
  • @Before 帶上@Test的方法執(zhí)行前會(huì)執(zhí)行該方法
  • @After 帶上@Test的方法執(zhí)行完畢后會(huì)執(zhí)行該方法
  • @BeforeClass 加上這個(gè)注解,則該方法會(huì)第一個(gè)執(zhí)行(在所有方法中),且方法要加上關(guān)鍵詞static,是一個(gè)static方法
  • @AfterClass 加上這個(gè)注解,則該方法最后一個(gè)執(zhí)行(在所有方法中),同樣,方法要加上關(guān)鍵詞static,是一個(gè)static方法

詳細(xì)的使用,大家可自行谷歌下,畢竟常用的也就前面三個(gè)了,(┬_┬)

基于ContiPerf的性能測(cè)試

ContiPerf是一個(gè)輕量級(jí)的測(cè)試工具,基于JUnit 4 開發(fā),可用于效率測(cè)試等?梢灾付ㄔ诰程數(shù)量和執(zhí)行次數(shù),通過(guò)限制最大時(shí)間和平均執(zhí)行時(shí)間來(lái)進(jìn)行性能測(cè)試。

性能測(cè)試示例

0.加入pom依賴包。

<dependency>
    <groupId>org.databene</groupId>
    <artifactId>contiperf</artifactId>
    <version>2.3.4</version>
    <scope>test</scope>
</dependency>

1.改寫UnitTestServiceTest測(cè)試類,進(jìn)入ContiPerfRule。
題外話:@RuleJunit提供的一個(gè)擴(kuò)展接口注解,其接口類為:org.junit.rules.MethodRule,注意在Junit5中,已經(jīng)被TestRule所以替代了。這里只是簡(jiǎn)單提下,因?yàn)榫唧w的也不是很清楚,也沒有深入了解過(guò)。

/**
 * 編寫接口測(cè)試類
 * @author oKong
 *
 */
@RunWith(SpringRunner.class)
//SpringBootTest 是springboot 用于測(cè)試的注解,可指定啟動(dòng)類或者測(cè)試環(huán)境等,這里直接默認(rèn)。
@SpringBootTest 
public class UnitTestServiceTest {
	
	@Autowired
	UnitTestService testService;
	
	//引入 ContiPerf 進(jìn)行性能測(cè)試
	@Rule
	public ContiPerfRule contiPerfRule = new ContiPerfRule();
	
	@Test
	//10個(gè)線程 執(zhí)行10次
	@PerfTest(invocations = 100,threads = 10)
	public void test() {
		String msg = "this is a test";
		String result = testService.process(msg);
		//斷言 是否和預(yù)期一致
		Assert.assertEquals(msg, result);
	}
}

 

  1. 控制臺(tái)會(huì)有性能報(bào)告,同時(shí)訪問(wèn):target/contiperf-report/index.html,會(huì)有圖表提示。

控制臺(tái)輸出:

cn.lqdev.learning.springboot.chapter13.service.UnitTestServiceTest.test
samples: 100
max:     403
average: 41.5
median:  15

測(cè)試報(bào)告:

測(cè)試報(bào)告測(cè)試報(bào)告

注解參數(shù)說(shuō)明

@PerfTest

  • invocations:執(zhí)行次數(shù)n,與線程數(shù)量無(wú)關(guān),默認(rèn)值為1
  • threads:線程池?cái)?shù)量n,并發(fā)執(zhí)行n個(gè)線程
  • duration:重復(fù)地執(zhí)行時(shí)間n,測(cè)試至少執(zhí)行n毫秒

@Required

  • throughput:吞吐要求n,要求每秒至少執(zhí)行n個(gè)測(cè)試
  • average:平均執(zhí)行時(shí)間n,要求平均執(zhí)行時(shí)間不超過(guò)n毫秒
  • max:最大執(zhí)行時(shí)間n,要求最大的執(zhí)行時(shí)間不超過(guò)n毫秒
  • totalTime:總執(zhí)行時(shí)間n,要求總的執(zhí)行時(shí)間不超過(guò)n毫秒
  • median:50%平均執(zhí)行時(shí)間n,要求所有執(zhí)行的50%測(cè)試平均執(zhí)行時(shí)間不超過(guò)n毫秒
  • percentile90:90%平均執(zhí)行時(shí)間n,要求所有執(zhí)行的90%測(cè)試平均執(zhí)行時(shí)間不超過(guò)n毫秒
  • percentile95:95%平均執(zhí)行時(shí)間n,要求所有執(zhí)行的95%測(cè)試平均執(zhí)行時(shí)間不超過(guò)n毫秒
  • percentile99:99%平均執(zhí)行時(shí)間n,要求所有執(zhí)行的99%測(cè)試平均執(zhí)行時(shí)間不超過(guò)n毫秒
  • percentiles:表達(dá)式”a:n,b:m”,要求a%的測(cè)試不超過(guò)n毫秒,b%的測(cè)試不超過(guò)m毫秒

總結(jié)

本章節(jié)主要是對(duì)JunitContiPerf的使用簡(jiǎn)單的示例,像MockMvc的詳細(xì)用法并沒有深入,大家可自行搜索下,畢竟我也用的不多呀。

最后

目前互聯(lián)網(wǎng)上很多大佬都有SpringBoot系列教程,如有雷同,請(qǐng)多多包涵了。本文是作者在電腦前一字一句敲的,每一步都是實(shí)踐的。若文中有所錯(cuò)誤之處,還望提出,謝謝。

標(biāo)簽: 代碼 谷歌 互聯(lián)網(wǎng) 開發(fā)者 搜索

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:SpringBoot | 第十四章:基于Docker的簡(jiǎn)單部署

下一篇:iOS 利用AFNetworking實(shí)現(xiàn)大文件分片上傳