摘要:?jiǎn)卧獪y(cè)試因?yàn)楣締卧獪y(cè)試覆蓋率需要達(dá)到,所以進(jìn)行單元測(cè)試用例編寫。測(cè)試的時(shí)候可以把每個(gè)判斷分支都走到。同這句代碼,可以通過如此一個(gè)對(duì)象,使用以上方法基本上可以編寫所有代碼的測(cè)試類。編寫測(cè)試一定程度上可以發(fā)現(xiàn)代碼錯(cuò)誤,可以借此重構(gòu)代碼。
3.springboot單元測(cè)試
因?yàn)楣締卧獪y(cè)試覆蓋率需要達(dá)到80%,所以進(jìn)行單元測(cè)試用例編寫。多模塊項(xiàng)目的因?yàn)闀?huì)經(jīng)常調(diào)用其他服務(wù),而且避免數(shù)據(jù)庫(kù)操作對(duì)于數(shù)據(jù)庫(kù)造成影響,所以所有的操作都要mock掉,也就是模擬調(diào)用的結(jié)果。測(cè)試用例編寫可以參考https://www.journaldev.com/21...,上面介紹也比較詳細(xì),不過以下介紹是自己遇到的一些問題。
3.1配置文件
6.14.3 4.12 2.19.0 2.0.0-beta.5 org.springframework.boot spring-boot-starter-test test org.testng testng ${testng.version} test junit junit ${junit4.version} test org.mockito mockito-core ${mockito-core.version} test org.powermock powermock-module-testng ${powermock.version} test org.powermock powermock-module-junit4 ${powermock.version} test org.powermock powermock-api-mockito2 ${powermock.version} test
可以參考如https://www.journaldev.com/21...
這三個(gè)依賴是支持靜態(tài)類mock所需要的,還有一個(gè)版本的問題,之前
java.lang.NoSuchMethodError: org.mockito.internal.handler.MockHandlerFactory.createMockHandler(Lorg/mockito/mock/MockCreationSettings;)Lorg/mockito/internal/InternalMockHandler;
的報(bào)錯(cuò),修改了版本后來(lái)得到了解決。
3.2.沒有靜態(tài)方法調(diào)用
要測(cè)的serverImpl類使用@InjectMocks,其他所有的依賴的類使用@Mock掉,這樣可以模擬依賴的類的實(shí)現(xiàn)而不是調(diào)用依賴類的實(shí)現(xiàn),放置比如調(diào)用數(shù)據(jù)庫(kù)操作導(dǎo)致的問題。類上使用@RunWith(SpringRunner.class)注解。
一下為測(cè)試代碼,withLearningService.getGift(passId, code, token, ip)里面會(huì)用到paramUtil.getParamByParamName(PRODUCT_CODE)以及openApiService.userQueryInfoById(anyString()),所以我們需要把用到的兩個(gè)方法模擬它的返回結(jié)果。
when(paramUtil.getParamByParamName(PRODUCT_CODE)).thenReturn(productCode); when(openApiService.userQueryInfoById(anyString())).thenReturn(intevee); withLearningService.getGift(passId, code, token, ip);
使用when模擬paramUtil的返回結(jié)果,也可以使用any()模擬對(duì)象,anyString()來(lái)字符串,還有anyInt(),anyLong()模擬其他類型參數(shù)。測(cè)試的時(shí)候可以把每個(gè)判斷分支都走到。
如果類加上@SpringBootTest注解的話項(xiàng)目會(huì)啟動(dòng)springboot項(xiàng)目加載各種配置,速度會(huì)慢很多,建議直接都mock掉不需要啟動(dòng)springboot環(huán)境。
3.3需要使用靜態(tài)方法
類上使用
@RunWith(PowerMockRunner.class)
@PrepareForTest({ HttpsUtils.class, RedisUtil.class, SpringContextUtil.class,AESUtil.class,KeyGenerator.class })
兩個(gè)注解,需要使用靜態(tài)方法的類添加到@PrepareForTest的參數(shù)里面。一般的靜態(tài)方法調(diào)用直接使用:
PowerMockito.mockStatic(RedisUtil.class); PowerMockito.when(RedisUtil.get(anyString())).thenReturn("0");
但是如上面的這個(gè)調(diào)用會(huì)產(chǎn)生類似:
的錯(cuò)誤,RedisUtil是我司自己封裝的Redis操作工具類,查看RedisUtil.get方法,看到需要注入spring的上下文環(huán)境ApplicationContext applicationContext。所以需要添加該上下文環(huán)境
PowerMockito.mockStatic(SpringContextUtil.class); PowerMockito.when(SpringContextUtil.getApplicationContext()).thenReturn(new XmlWebApplicationContext()); PowerMockito.mockStatic(RedisUtil.class); PowerMockito.when(RedisUtil.get(anyString())).thenReturn("0");
這樣可以解決問題,我自己編寫的過程中遇到了一個(gè)加解密類報(bào)錯(cuò),工具類代碼如下
if (key == null || content == null || content.isEmpty()) { return null; } String msg = null; byte[] byteRresult = new byte[content.length() / 2]; for (int i = 0; i < content.length() / 2; i++) { int high = Integer.parseInt(content.substring(i * 2, i * 2 + 1), 16); int low = Integer.parseInt(content.substring(i * 2 + 1, i * 2 + 2), 16); byteRresult[i] = (byte) (high * 16 + low); } try { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); byte[] result = cipher.doFinal(byteRresult); return new String(result);
測(cè)試類的mock編寫如入下:
PowerMockito.mockStatic(AESUtil.class); PowerMockito.when(AESUtil.decrypt(anyString(), anyString())).thenReturn("11");
這樣編寫報(bào)錯(cuò),改為以下則完成測(cè)試用例編寫。
PowerMockito.mockStatic(KeyGenerator.class); KeyGenerator keyg = Mockito.mock(KeyGenerator.class); PowerMockito.when(KeyGenerator.getInstance(anyString())).thenReturn(keyg); PowerMockito.mockStatic(AESUtil.class); PowerMockito.when(AESUtil.decrypt(anyString(), anyString())).thenReturn("11");
同KeyGenerator keyg = Mockito.mock(KeyGenerator.class);這句代碼,可以通過如此mock一個(gè)對(duì)象,使用以上方法基本上可以編寫所有代碼的測(cè)試類。這里的測(cè)試最好都是針對(duì)server層進(jìn)行測(cè)試,為什么不對(duì)controller層也進(jìn)行測(cè)試,其實(shí)主要是單元測(cè)試的意義是把基本的邏輯跑通,controller層的測(cè)試一定程度上可以交由測(cè)試進(jìn)行測(cè)試,單元測(cè)試如果要覆蓋到每一個(gè)判斷分支也是不好寫的,比較痛苦。編寫測(cè)試一定程度上可以發(fā)現(xiàn)代碼錯(cuò)誤,可以借此重構(gòu)代碼。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/74307.html
摘要:熱加載代表的是我們不需要重啟服務(wù)器,就能夠類檢測(cè)得到,重新生成類的字節(jié)碼文件無(wú)論是熱部署或者是熱加載都是基于類加載器來(lái)完成的。驗(yàn)證階段字節(jié)碼文件不會(huì)對(duì)造成危害準(zhǔn)備階段是會(huì)賦初始值,并不是程序中的值。 一、SpringBoot入門 今天在慕課網(wǎng)中看見了Spring Boot這么一個(gè)教程,這個(gè)Spring Boot作為JavaWeb的學(xué)習(xí)者肯定至少會(huì)聽過,但我是不知道他是什么玩意。 只是大...
摘要:本博客貓叔的博客,轉(zhuǎn)載請(qǐng)申明出處本系列教程為項(xiàng)目附帶。歷史文章如何在安裝最新版安裝安裝最新版的入門教程的入門教程安裝教程安裝流程安裝如果不清楚是什么,請(qǐng)查看的文檔和簡(jiǎn)介,這里給出的安裝過程安裝虛擬機(jī)如果有遠(yuǎn)程服務(wù)器的,請(qǐng)略過此步驟本文推 本博客 貓叔的博客,轉(zhuǎn)載請(qǐng)申明出處本系列教程為HMStrange項(xiàng)目附帶。 Auth:HMStrange-TIAN e-mail:zhangqihao...
摘要:這里有一個(gè)參數(shù),主要是用來(lái)指定該配置項(xiàng)在配置文件中的前綴。創(chuàng)建一個(gè)配置類,里面沒有顯式聲明任何的,然后將剛才創(chuàng)建的導(dǎo)入。創(chuàng)建實(shí)現(xiàn)類,返回的全類名。創(chuàng)建實(shí)現(xiàn)類,實(shí)現(xiàn)方法直接手動(dòng)注冊(cè)一個(gè)名叫的到容器中。前言 小伙伴們是否想起曾經(jīng)被 SSM 整合支配的恐懼?相信很多小伙伴都是有過這樣的經(jīng)歷的,一大堆配置問題,各種排除掃描,導(dǎo)入一個(gè)新的依賴又得添加新的配置。自從有了 SpringBoot 之后,咋...
閱讀 1392·2019-08-30 12:54
閱讀 1878·2019-08-30 11:16
閱讀 1621·2019-08-30 10:50
閱讀 2455·2019-08-29 16:17
閱讀 1275·2019-08-26 12:17
閱讀 1387·2019-08-26 10:15
閱讀 2396·2019-08-23 18:38
閱讀 793·2019-08-23 17:50