Java_UT_Mock系列之-01 Powermock與Thead.sleep

測(cè)試場(chǎng)景及問題

筆者在對(duì)某個(gè)JAVA socket通信程序進(jìn)行UT的時(shí)候浊猾,遇到過以下一個(gè)場(chǎng)景槐沼,
客戶端發(fā)出登陸請(qǐng)求,然后每隔500ms監(jiān)查一下底層通信機(jī)的登陸狀態(tài)润绵,如果登陸成功线椰,底層通信機(jī)會(huì)將其狀態(tài)修改為L(zhǎng)OGIN_SUCCESS/LOGIN_FAILED〕九危客戶端檢查時(shí)如果發(fā)現(xiàn)登陸狀態(tài)不是上述兩個(gè)狀態(tài)憨愉,則線程休眠500ms然后繼續(xù)監(jiān)查。上述邏輯要重復(fù)30次卿捎,也就是15秒后配紫,如果登陸狀態(tài)不是上述成功/失敗的狀態(tài),則表示未收到登陸答復(fù)等邏輯午阵,需要切換服務(wù)器繼續(xù)登陸躺孝。
一個(gè)簡(jiǎn)化的過程如下:

public class SystemClass {
int j=0;
public void callThead() {
for(int i=0;i<30;i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
//e.printStackTrace();
break;
}
//end for
j++;
}
}

為了模擬登陸請(qǐng)求未收到答復(fù)的場(chǎng)景(如網(wǎng)絡(luò)延遲),需要走完整個(gè)循環(huán)底桂,也就是說(shuō)需要等待500*30ms=15s的時(shí)間括细。對(duì)于UT 來(lái)說(shuō),這個(gè)時(shí)間是無(wú)法接受的戚啥。
解決辦法及代碼
因此奋单,我們需要對(duì)Thread.class進(jìn)行mock,縮短等待時(shí)間猫十。 方案是在Thread.sleep方法被調(diào)用時(shí)览濒,直接拋出InterruptedException 呆盖,讓程序退出整個(gè)循環(huán)。示例程序如下:

import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.rule.PowerMockRule;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.doThrow;
import static org.junit.Assert.assertEquals;
/**
* Test class to demonstrate static mocking with PowerMockito.
*/
//@RunWith(PowerMockRunner.class)  // using @Rule
@PrepareForTest( { SystemClass.class})
public class SystemClassTest {
    @Rule
  public PowerMockRule rule = new PowerMockRule();
@Test
public void testMockStaticThatThrowsException() throws Exception {
spy(Thread.class);
// Expectations
doThrow(new InterruptedException()).when(Thread.class);
Thread.sleep(Mockito.anyLong());
//Test
SystemClass systemClass = new SystemClass();
systemClass.callThead();
assertEquals(0, systemClass.j);
}
}

案例分析

對(duì)于mock的挑戰(zhàn)有兩個(gè)贷笛,首先Thread.sleep是一個(gè)靜態(tài)方法应又;其次,該方法沒有返回值乏苦。對(duì)于Mockito等mock工具來(lái)說(shuō)株扛,這就是無(wú)法解決的問題了。得益于Powermockito對(duì)于靜態(tài)方法進(jìn)行Mock的能力汇荐,使用如下格式洞就,就實(shí)現(xiàn)了預(yù)期的調(diào)用Thread.sleep時(shí)拋出中斷異常的行為,從而實(shí)現(xiàn)了大大縮短程序執(zhí)行時(shí)間的目標(biāo)掀淘。
// Expectations
doThrow(new InterruptedException()).when(Thread.class);
Thread.sleep(Mockito.anyLong());
當(dāng)然旬蟋,為了能夠mock某個(gè)類的靜態(tài)方法,需要在測(cè)試類上加上一下注解革娄,
@PrepareForTest( { SystemClass.class})
并且使用Powermockito.spy這個(gè)方法來(lái)部分mock Thread這個(gè)類倾贰。
spy(Thread.class);
另外,通過以下斷言也能證實(shí)上述mock效果的有效性拦惋。
assertEquals(0, systemClass.j);
由于在循環(huán)的第一次執(zhí)行過程中就中斷退出匆浙,因此變量j==0;
實(shí)際程序中的斷言也可參考這種方式。

遺留問題

由于Thread.class來(lái)自java.lang厕妖,是Java語(yǔ)言的一部分吞彤,因此對(duì)于Thread的mock會(huì)引起同樣需要修改java 字節(jié)碼的jacoco覆蓋率統(tǒng)計(jì)工具的沖突,導(dǎo)致無(wú)法dump測(cè)試覆蓋率報(bào)告叹放。該問題將另文介紹饰恕。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市井仰,隨后出現(xiàn)的幾起案子埋嵌,更是在濱河造成了極大的恐慌,老刑警劉巖俱恶,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雹嗦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡合是,警方通過查閱死者的電腦和手機(jī)了罪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)聪全,“玉大人泊藕,你說(shuō)我怎么就攤上這事∧牙瘢” “怎么了娃圆?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵玫锋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我讼呢,道長(zhǎng)撩鹿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任悦屏,我火速辦了婚禮节沦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘础爬。我一直安慰自己甫贯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布幕帆。 她就那樣靜靜地躺著获搏,像睡著了一般赖条。 火紅的嫁衣襯著肌膚如雪失乾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天纬乍,我揣著相機(jī)與錄音碱茁,去河邊找鬼。 笑死仿贬,一個(gè)胖子當(dāng)著我的面吹牛纽竣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播茧泪,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蜓氨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了队伟?” 一聲冷哼從身側(cè)響起穴吹,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嗜侮,沒想到半個(gè)月后港令,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锈颗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年顷霹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片击吱。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淋淀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出覆醇,到底是詐尸還是另有隱情绅喉,我是刑警寧澤渠鸽,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站柴罐,受9級(jí)特大地震影響徽缚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜革屠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一凿试、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧似芝,春花似錦那婉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至寞奸,卻和暖如春呛谜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枪萄。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工隐岛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓷翻。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓聚凹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親齐帚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子妒牙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)对妄,斷路器湘今,智...
    卡卡羅2017閱讀 134,652評(píng)論 18 139
  • 在這春暖花開的日子,突然一下子變的這么冷饥伊,真是不適應(yīng)象浑,早上給孩子穿少了,總怕她上午會(huì)冷琅豆,不過小孩就是火力旺愉豺,...
    董紫涵閱讀 203評(píng)論 0 1
  • 修仙文一般都是幾百萬(wàn)字,一個(gè)不好就會(huì)爛尾或者寫崩茫因,一篇好看的修仙文真的是可遇而不可求蚪拦。 今天我要推薦的這一本是一本...
    兔子的大板牙閱讀 506評(píng)論 0 0
  • 月亮藏在大樹后面 山坡笑了它 這張害羞的臉 永遠(yuǎn)不會(huì)變 要不是因?yàn)閻壑厍?才不會(huì)守護(hù) 或者算是流浪 地球又愛了太...
    會(huì)飛的馬閱讀 268評(píng)論 0 2
  • 昨天看吳曉波的演講,他回憶到他畢業(yè)后的經(jīng)歷,畢業(yè)后他在新華社工作了13年驰贷,跟他同個(gè)辦公室的老同志過兩年就退休盛嘿,單位...
    中正之勢(shì)閱讀 293評(píng)論 0 1