精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

使用 PowerMock 寫單元測試,被坑慘了!

開發 前端
PowerMock 寫單測對開發人員來說確實很方便,但是如果工程中的代碼量比較大,團隊又要求單測覆蓋率高,那單測類的數量確實會很多,最終結果就是單測耗時時間很長。這種情況并不適合使用 PowerMock 框架。

大家好,我是君哥。

最近在工作中遇到一個不太好解決的問題,我負責的系統單元測試跑的非常慢,有時候甚至超過 2 個半小時。

公司要求上線前流水線里面的單測必須全部跑成功。跑流水線的時候如果有單測跑失敗,需要修改后重新跑,又得跑 2 個多小時。極端情況下得反反復復來幾次,真的讓人感到煎熬。有時候發現測試用例跑失敗的原因竟然是 OOM。

今天就來聊一聊造成單測跑的慢的罪魁禍首,PowerMock。

1.PowerMock 基礎

要說 PowerMock 怎么樣,那是真的非常好用。下面列給出幾個示例,先上一段業務代碼,然后我們通過 3 個測試用例把這段代碼單測覆蓋率寫到 100%。

1  public class FileParser {
2  
3      private Logger logger = LoggerFactory.getLogger(getClass());
4  
5      @Resource
6      private UserRepository userRepository;
7  
8      public void parseFile(String fileName) {
9          File file = new File(fileName);
10          if (!file.exists()){
11              return;
12          }
13          try {
14              BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
15              String line = null;
16              while ((line = bufferedReader.readLine())!= null){
17                  User user = userRepository.getUser(line);
18                  logger.info("user with name{}:{}", line, user);
19              }
20         }catch (IOException e){
21             throw new RuntimeException(e);
22         }
23     }
24 }

這段代碼涉及到讀文件、依賴注入、異常處理,我們寫單測也從這三個方面來完成。

1.1 文件不存在

我們先來模擬一下文件不存在,這個用例覆蓋到上面文件不存在的判斷。測試用例如下 :

@Test
public void testParseFile_not_exists() throws Exception {
 File file = PowerMockito.mock(File.class);
 PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(file);
 when(file.exists()).thenReturn(false);
 fileParser.parseFile("123");
 Mockito.verify(userRepository, Mockito.times(0)).getUser(anyString());
}

這里使用 PowerMock 方便地模擬了第 11 行代碼文件不存在,用例成功。

1.2 循環跳出

這段用例要模擬按行讀文件、dao 層查詢用戶、跳出循環這三個代碼,測試用例代碼如下:

@Test
public void testParseFile_exists() throws Exception {
 File file = PowerMockito.mock(File.class);
 PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(file);
 when(file.exists()).thenReturn(true);

 FileInputStream fileInputStream = PowerMockito.mock(FileInputStream.class);
 PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenReturn(fileInputStream);

 InputStreamReader inputStreamReader = PowerMockito.mock(InputStreamReader.class);
 PowerMockito.whenNew(InputStreamReader.class).withAnyArguments().thenReturn(inputStreamReader);

 BufferedReader bufferedReader = PowerMockito.mock(BufferedReader.class);
 PowerMockito.whenNew(BufferedReader.class).withAnyArguments().thenReturn(bufferedReader);

 //模擬循環和跳出
 when(bufferedReader.readLine()).thenReturn("testUser").thenReturn("user").thenReturn(null);
 User user = PowerMockito.mock(User.class);
 when(userRepository.getUser(anyString())).thenReturn(user);

 fileParser.parseFile("123");

 Mockito.verify(userRepository, Mockito.times(1)).getUser(anyString());
}

這段用例跑完后,已經覆蓋到源代碼的第 17行和 19 行。

1.3 模擬異常

源代碼中有一個異常處理,用例要達到 100% 覆蓋,必須把這個異常用測試用例模擬出來。下面看一下測試用例:

@Test(expected = RuntimeException.class)
public void testParseFile_exception() throws Exception {
    File file = PowerMockito.mock(File.class);
    PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(file);
    when(file.exists()).thenReturn(true);

    FileInputStream fileInputStream = PowerMockito.mock(FileInputStream.class);
    PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenReturn(fileInputStream);

    InputStreamReader inputStreamReader = PowerMockito.mock(InputStreamReader.class);
    PowerMockito.whenNew(InputStreamReader.class).withAnyArguments().thenReturn(inputStreamReader);

    BufferedReader bufferedReader = PowerMockito.mock(BufferedReader.class);
    PowerMockito.whenNew(BufferedReader.class).withAnyArguments().thenReturn(bufferedReader);

    //模擬拋出異常
    when(bufferedReader.readLine()).thenThrow(new IOException());

    fileParser.parseFile("123");
}

至此,單測覆蓋率達到 100%。

2.PowerMock 進階

下面再來使用幾個 PowerMock 的功能。再來一段示例代碼:

1   public void parseFileWithScanner(String fileName) {
2    File file = new File(fileName);
3    if (!file.exists()){
4     return;
5    }
6    try {
7     Scanner scanner = new Scanner(file);
8     String line = null;
9     while (scanner.hasNextLine()){
10     line = scanner.nextLine();
11     if (StringUtils.equals(line, "testUser")){
12      User user = userRepository.getUser(line);
13      logger.info("user with name{}:{}", line, user);
14     }
15    }
16   }catch (IOException e){
17    throw new RuntimeException(e);
18   }
19  }

這次我們也要增加 2 個用例的 mock,一個是 Scanner 這個 final 類,第二個是 StringUtils 這個靜態類。

2.1 final 類

雖然是一個 final 類,但使用了 PowerMock 框架,我們就像普通類一樣就可以用例。

@Test
public void testParseFile_scanner() throws Exception {
 File file = PowerMockito.mock(File.class);
 PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(file);
 when(file.exists()).thenReturn(true);

 Scanner scanner = PowerMockito.mock(Scanner.class);
 PowerMockito.whenNew(Scanner.class).withAnyArguments().thenReturn(scanner);

 //模擬循環
 when(scanner.hasNextLine()).thenReturn(true).thenReturn(true).thenReturn(false);
 when(scanner.nextLine()).thenReturn("testUser").thenReturn("user");

 User user = PowerMockito.mock(User.class);
 when(userRepository.getUser(anyString())).thenReturn(user);

 fileParser.parseFileWithScanner("123");

 Mockito.verify(userRepository, Mockito.times(1)).getUser(anyString());
}

除了 final 類,抽象類、接口都可以 mock,確實很方便。

2.2 靜態類

PowerMock 可以方便地模擬靜態類,下面這個測試用例對 StringUtils 這個靜態類進行了 mock,每次 equals 方法都是返回 false。

@Test
public void testParseFile_StringUtils() throws Exception {
 File file = PowerMockito.mock(File.class);
 PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(file);
 when(file.exists()).thenReturn(true);

 Scanner scanner = PowerMockito.mock(Scanner.class);
 PowerMockito.whenNew(Scanner.class).withAnyArguments().thenReturn(scanner);

 //模擬循環
 when(scanner.hasNextLine()).thenReturn(true).thenReturn(true).thenReturn(false);
 when(scanner.nextLine()).thenReturn("testUser").thenReturn("user");
 when(StringUtils.equals(anyString(), anyString())).thenReturn(false).thenReturn(false);
 User user = PowerMockito.mock(User.class);
 when(userRepository.getUser(anyString())).thenReturn(user);

 fileParser.parseFileWithScanner("123");

 Mockito.verify(userRepository, Mockito.times(0)).getUser(anyString());
}

因為 equals 方法一直返回 false,所以 getUser 方法沒有執行到,測試用例中 verify getUser 方法被調用 0 次。需要注意的是,模擬靜態類需要在類定義上面加上一個注解,然后對靜態類要做一次 mockStatic。看下面的 @Before 注解。

@RunWith(PowerMockRunner.class)
@PrepareForTest({FileParser.class, StringUtils.class})
public class FileParserTest {

@Before
public void before(){
 PowerMockito.mockStatic(StringUtils.class);
}

3.原因分析

PowerMock 因為使用了 @PrepareForTest、@PowerMockIgnore、@SuppressStaticInitialzationFor 這三個注解,這三個注解的參數值不一樣,會導致每個單測類執行的時候不能復用公有類加載器,而是需要創建一個自己獨有的類加載器。這導致類加載過程十分耗時。

在單測類數量比較少的情況下,單測耗時問題是不會出現的,但是如果一個工程中的單測類數據猛增,比如我們的單測類在 600+,問題就暴露出來的。最難的是不太好做優化,因為如果要去掉 PowerMock 框架,要改造的東西太多了。

4.最后

PowerMock 寫單測對開發人員來說確實很方便,但是如果工程中的代碼量比較大,團隊又要求單測覆蓋率高,那單測類的數量確實會很多,最終結果就是單測耗時時間很長。這種情況并不適合使用 PowerMock 框架。

圖片圖片

同時我們也要看到,PowerMock 最近一次核心代碼更新已經是 4 年前了,單測類數據量多導致的內存問題、耗時問題并沒有解決。所以選型的時候一定要慎重。

責任編輯:武曉燕 來源: 君哥聊技術
相關推薦

2021-05-05 11:38:40

TestNGPowerMock單元測試

2021-03-11 12:33:50

JavaPowerMock技巧

2020-03-20 08:00:32

代碼程序員追求

2021-07-16 07:57:35

SpringBootOpenFeign微服務

2017-01-16 12:12:29

單元測試JUnit

2017-01-14 23:26:17

單元測試JUnit測試

2017-01-14 23:42:49

單元測試框架軟件測試

2020-09-11 16:00:40

Bash單元測試

2021-10-12 19:16:26

Jest單元測試

2017-03-23 16:02:10

Mock技術單元測試

2023-07-26 08:58:45

Golang單元測試

2012-05-17 09:09:05

Titanium單元測試

2013-06-04 09:49:04

Spring單元測試軟件測試

2025-04-22 03:00:00

模型SpringAI

2024-10-16 16:09:32

2021-03-28 23:03:50

Python程序員編碼

2010-03-04 15:40:14

Python單元測試

2025-08-28 01:00:00

Go單元測試

2020-08-18 08:10:02

單元測試Java

2019-01-29 09:00:44

PyHamcrest單元測試框架
點贊
收藏

51CTO技術棧公眾號

国产精品xxx在线观看| 成人黄色网址| 日韩成人午夜精品| 日韩在线小视频| 99999精品| 性欧美xxx69hd高清| 国产精品久久久久天堂| 国产精品乱子乱xxxx| 欧美人一级淫片a免费播放| 欧美hd在线| 日韩精品黄色网| 日本美女视频一区| 一区二区三区短视频| 亚洲人成7777| 欧洲精品码一区二区三区免费看| 99热这里只有精品9| 香蕉精品999视频一区二区| 久久夜精品va视频免费观看| 色呦呦一区二区| 日本一区二区三区播放| 日本精品一区二区三区高清 | 日韩av色在线| 国产亚洲第一页| 国产韩日影视精品| 亚洲欧美中文日韩在线| 美女伦理水蜜桃4| 成人在线分类| 欧美日韩在线综合| 日本va中文字幕| 久久影院午夜精品| 一区二区三区不卡在线观看| 中文字幕中文字幕99| 欧美偷拍视频| 91美女福利视频| 国产一区二区三区黄| 99热这里只有精品99| 理论电影国产精品| 国产精品嫩草影院久久久| 日韩欧美成人一区二区三区| 亚洲福利一区| 国色天香2019中文字幕在线观看| 欧美风情第一页| 欧美wwwww| 中文字幕亚洲色图| 国产91丝袜美女在线播放| 自拍亚洲一区| 亚洲欧美国内爽妇网| 人妻无码一区二区三区| 久久久久97| 日韩av最新在线观看| 男人网站在线观看| 都市激情亚洲| 国产丝袜一区二区| 中文字幕第4页| 加勒比久久综合| 一区二区av在线| 亚洲不卡的av| 久久久久久久久久久妇女| 日韩有码在线播放| 破处女黄色一级片| 国产一区亚洲| 午夜精品免费视频| 五月婷婷色丁香| 日本少妇一区二区| 成人a免费视频| 99免费在线视频| 国产成人精品三级| 国产精品一区二| 日本成人一区二区三区| 国产日韩欧美综合在线| 亚洲a∨一区二区三区| 欧美三级黄网| 亚洲综合久久久久| 国产免费黄视频| 色成人免费网站| 欧美二区在线观看| 女性生殖扒开酷刑vk| 久久不卡国产精品一区二区 | 1区2区在线观看| 亚洲国产成人91porn| 人妻精品无码一区二区三区| 欧洲成人一区| 日韩一区二区视频| 欧美黑人欧美精品刺激| 第一社区sis001原创亚洲| 久久视频国产精品免费视频在线| 久久婷婷国产麻豆91| 久久久噜噜噜久久狠狠50岁| 国产一区红桃视频| 蜜臀av午夜精品| 日本一区二区三区国色天香| 国产成人三级视频| 涩涩涩在线视频| 欧美精品一卡两卡| 蜜臀av粉嫩av懂色av| 郴州新闻综合频道在线直播| 欧美日韩国产91| 波多野结衣电车痴汉| 国产精品自拍三区| 日韩aⅴ视频一区二区三区| a级网站在线播放| 色妞www精品视频| gogo亚洲国模私拍人体| 国产一区二区电影在线观看| 欧美激情精品久久久久久黑人 | 黄色香蕉视频在线观看| 国产亚洲毛片| 91丝袜脚交足在线播放| 成人性爱视频在线观看| 亚洲成av人影院| 亚洲网中文字幕| 国产欧美日韩精品一区二区三区 | 亚洲人a成www在线影院| 清纯粉嫩极品夜夜嗨av| 蜜桃视频在线观看一区二区| 精品欧美一区二区久久久伦| av免费在线网站| 欧美日韩一级大片网址| 日本一级免费视频| 国产欧美激情| 国产精品二区三区| av免费在线网站| 欧美日韩亚洲综合在线 欧美亚洲特黄一级| 污污内射在线观看一区二区少妇| 亚洲色图二区| 成人av番号网| 77777影视视频在线观看| 天天av天天翘天天综合网 | 色在人av网站天堂精品| 影音先锋黄色网址| 国产亚洲欧美一级| 色欲av无码一区二区人妻| 9国产精品午夜| 久操成人在线视频| av网站免费播放| 亚洲色图视频网站| 手机免费看av网站| 天天射天天综合网| 国产欧美日韩免费| 自拍视频在线| 欧美精品在线观看播放| 激情无码人妻又粗又大| 美女性感视频久久| 亚洲欧美久久久久一区二区三区| 日韩毛片一区| 在线精品国产欧美| 亚洲一区 中文字幕| 欧美极品aⅴ影院| 黄色片在线免费| 欧美三级伦理在线| 国产欧美在线观看| 麻豆传媒在线完整视频| 欧美高清精品3d| 久久精品黄色片| 福利一区福利二区| 青青草精品视频在线| 欧美激情久久久久久久久久久| 97超级碰在线看视频免费在线看| 亚洲区小说区图片区| 欧美午夜影院在线视频| 超碰97av在线| 精品亚洲成a人在线观看| 超碰10000| 草草视频在线一区二区| 97久久超碰福利国产精品…| 天堂av网在线| 欧美性猛片aaaaaaa做受| 啪啪一区二区三区| 国产成人午夜片在线观看高清观看| 屁屁影院ccyy国产第一页| 久久久久久久久久久久久久久久久久久久| 午夜精品理论片| 国产视频第一页在线观看| 欧美日韩一本到| 久久综合综合久久| 久久色.com| 中文字幕线观看| 亚洲国产片色| 五月天丁香综合久久国产| www.久久99| 亚洲91av视频| 在线观看a视频| 精品女同一区二区| 精品国产乱子伦| 亚洲手机成人高清视频| 污污污www精品国产网站| 久久精品亚洲| 肉大捧一出免费观看网站在线播放| 欧美偷窥清纯综合图区| 国产免费一区视频观看免费| 牛牛电影国产一区二区| 国产午夜精品一区理论片飘花| 国产欧美综合视频| 欧美午夜性色大片在线观看| 一区视频免费观看| 久久精品在线观看| 国产老头和老头xxxx×| 天堂资源在线中文精品| 激情成人开心网| 欧美午夜精彩| 国内一区二区三区在线视频| 欧美性www| 日韩美女视频免费看| 在线免费av导航| 一区二区三区亚洲| 视频一区二区免费| 91精品婷婷国产综合久久竹菊| 久久久久久久久久免费视频| 亚洲免费视频中文字幕| 久久国产柳州莫菁门| 成人性视频免费网站| www.成人黄色| 天堂一区二区在线免费观看| 一二三四视频社区在线| 在线中文字幕第一区| 三区精品视频观看| 妖精一区二区三区精品视频| 国产伦精品一区二区三区视频黑人 | 天堂网2014av| 日韩一区二区三区在线观看| 在线观看国产成人| 在线免费观看日本一区| aaa人片在线| 五月婷婷综合网| 国产一卡二卡在线播放| 亚洲色图在线视频| 青花影视在线观看免费高清| 国产精品视频一二| 亚洲国产天堂av| 久久免费的精品国产v∧| japanese在线观看| 成人午夜免费视频| 麻豆传媒在线看| 国产在线一区观看| 一区二区三区四区毛片| 蜜乳av一区二区三区| jizz欧美激情18| 日韩精品亚洲一区二区三区免费| 国产亚洲综合视频| 国产日韩亚洲| 黄色免费视频大全| 亚洲影院免费| 18禁免费无码无遮挡不卡网站| 最新成人av网站| 日韩精品 欧美| 影音先锋亚洲电影| 少妇高潮喷水在线观看| av成人黄色| 午夜精品久久久内射近拍高清| 男女精品视频| 欧美日韩在线成人| 麻豆成人在线观看| 亚洲涩涩在线观看| 国产精品99久| 一级全黄裸体片| 91伊人久久大香线蕉| xxxxx在线观看| 欧美高清在线视频| 好吊日在线视频| 一区二区三区在线视频观看58| 免费一级a毛片夜夜看| 亚洲大片免费看| 亚洲永久精品在线观看| 在线观看视频一区| 91丨porny丨在线中文| 日韩视频一区二区三区| 开心激情综合网| 亚洲欧洲激情在线| 日韩在线观看www| 欧美日韩第一视频| 草草视频在线| 国产精品久久国产精品99gif| 欧美性www| 国产伦精品一区二区三区视频黑人| 婷婷精品在线观看| 亚洲精品乱码久久久久久蜜桃91 | 成年人午夜免费视频| 久久福利毛片| 久久久久xxxx| 不卡欧美aaaaa| www久久久久久久| 伊人婷婷欧美激情| 依依成人综合网| 在线不卡免费av| 天天射,天天干| 在线日韩中文字幕| 免费在线播放电影| 日韩av日韩在线观看| 涩涩屋成人免费视频软件| 久久99精品久久久久久水蜜桃| 全球成人免费直播| 国产婷婷一区二区三区| 久久狠狠亚洲综合| 国产毛片毛片毛片毛片毛片毛片| 国产欧美一区二区精品性色超碰 | 伊人网在线视频观看| 亚洲男人电影天堂| 精产国品一区二区| 日韩免费性生活视频播放| 精品推荐蜜桃传媒| 欧美极品在线播放| 久久久久久久性潮| 免费看国产精品一二区视频| 午夜精品剧场| www.99av.com| 91在线国产观看| a级片在线观看免费| 欧美综合亚洲图片综合区| 丰满肥臀噗嗤啊x99av| 一区二区三区国产视频| 国产在线天堂www网在线观看| 亚洲尤物视频网| 第四色成人网| 久久精品网站视频| 波多野结衣亚洲一区| av激情在线观看| 欧美日韩国产综合草草| 久久电影中文字幕| 4p变态网欧美系列| 成人av影音| 日本福利视频在线观看| 精品一区二区三区在线播放视频| xxxx日本黄色| 狠狠躁夜夜躁人人躁婷婷91| 韩国中文字幕hd久久精品| 久久久av免费| 婷婷久久综合九色综合99蜜桃| 日本三级中国三级99人妇网站| 亚洲日产国产精品| 欧美69精品久久久久久不卡| 中文字幕一区二区三区在线不卡| 天天综合久久综合| 国产一区二区三区网站| 欧美极品免费| 日本一区二区在线| 日韩精品久久久久久| wwwwxxxx国产| 日韩欧美在线观看| 你懂得网站在线| 国产福利视频一区二区| 少妇一区二区视频| 黑鬼大战白妞高潮喷白浆| 久久久亚洲精品石原莉奈| 欧美日韩综合一区二区三区| 亚洲精品在线不卡| 欧美暴力调教| 亚洲欧美日韩国产成人综合一二三区 | 久久6免费高清热精品| 日本一区二区三区视频在线看| 日韩精品免费一区| 国产91露脸合集magnet| 日本少妇xxxx动漫| 亚洲精品久久久久久久久久久久| а√天堂8资源中文在线| 精品一区二区三区国产| 性欧美精品高清| a天堂中文字幕| 精品视频色一区| h网站久久久| 国产精品日韩欧美一区二区三区 | 男人天堂网在线视频| 97精品在线视频| 精品视频网站| 日本高清一区二区视频| 一级做a爱片久久| 午夜一区在线观看| 国产精品九九九| 亚洲男女av一区二区| 国产高潮失禁喷水爽到抽搐| 亚洲大片在线观看| 福利在线视频导航| 亚洲综合色av| 亚洲欧美日韩综合国产aⅴ| 亚洲欧美va天堂人熟伦| 7777精品伊人久久久大香线蕉 | 亚洲免费中文| 快灬快灬一下爽蜜桃在线观看| 91麻豆精品91久久久久同性| 高h视频在线播放| 日本一区视频在线| 国产一区在线精品| 久久精品视频7| 久久久国产一区二区| 精品欠久久久中文字幕加勒比| 国产三级三级三级看三级| 亚洲欧美另类久久久精品| 无码国产精品一区二区免费16| 国产精品视频网站| 影音先锋久久| 91免费公开视频| 日韩毛片在线观看| 精品精品视频| 欧美精品成人网| 亚洲国产综合视频在线观看| av影片在线看| 国产在线精品二区| 精品一区二区三区在线播放| 国产一级18片视频| 欧美精品性视频| 波多野结衣一区|