精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

欧美一级特黄aaaaaa| 正在播放亚洲1区| 午夜精品福利在线观看| 日本999视频| 亚洲经典一区二区| 北条麻妃国产九九九精品小说| 国产精品99久久久久久久vr| 日韩电影免费观看中文字幕| 中文字幕乱码免费| 国产天堂第一区| 久久亚州av| 亚洲黄色片在线观看| 国产精品福利无圣光在线一区| 日批视频免费看| 欧美成人精品一区二区男人看| 成人线上播放| 亚洲精品中文字幕乱码三区| 国产日韩在线播放| brazzers精品成人一区| 69av成人| 成人黄色av电影| 欧美国产高跟鞋裸体秀xxxhd| 国产精品久久a| 国产在线中文字幕| 午夜影院日韩| 亚洲第一福利网站| 国产乱淫av片杨贵妃| av网站在线免费看| 欧美影院一区| 欧美一区二区啪啪| 天天干天天色天天爽| 色婷婷av一区二区三区之红樱桃 | 欧美在线综合| 亚洲国产成人精品久久| 国产精品一区二区小说| 中文字幕日本在线| 狠狠色丁香久久婷婷综合丁香| 一区二区三区久久精品| 日本888xxxx| 北岛玲一区二区三区| 免费成人av在线| 精品国内产的精品视频在线观看| 91在线第一页| 中文字幕伦理免费在线视频| 丰满岳乱妇一区二区三区| 欧美激情久久久久| 来吧亚洲综合网| 一区二区三区视频播放| 一级特黄大欧美久久久| 国产九色91| 亚洲 欧美 日韩 综合| 一区三区在线欧| 欧美系列日韩一区| 亚洲黄色网址在线观看| 91短视频版在线观看www免费| 91麻豆文化传媒在线观看| 国产精品福利片| 日韩精品一区不卡| 国产精品伦理久久久久久| 日韩视频免费直播| 亚洲中文字幕无码中文字| av网站在线播放| 国产欧美日韩精品a在线观看| 91午夜理伦私人影院| 久久草视频在线| 精品视频网站| 日韩女同互慰一区二区| 99福利在线观看| 欧美性videos| 1024成人网| 精品国产综合久久| 奴色虐av一区二区三区| 欧美在线不卡| 欧美激情网友自拍| 欧美色图17p| 欧美三级午夜理伦三级小说| 欧美丰满一区二区免费视频| 黄色影院一级片| 欧美aa一级| 亚洲人成精品久久久久| 日本一区二区三区免费观看| 国产av无码专区亚洲av| 国产高清视频一区| 国产精品美女xx| 日本a一级在线免费播放| 国模娜娜一区二区三区| 亚洲一区国产精品| 成人黄色免费网| 久99久精品视频免费观看| 欧美在线性视频| avove在线播放| 久久国产成人精品| 日韩国产欧美精品一区二区三区| 久久精品一区二区免费播放| 亚洲一区二区三区中文字幕在线观看| 日韩欧美www| 午夜理伦三级做爰电影| 99精品一区| 性亚洲最疯狂xxxx高清| 中文字幕日日夜夜| 日韩黄色免费电影| 欧美在线观看一区二区三区| 精品无码黑人又粗又大又长| 91综合在线| 一区二区在线视频播放| 午夜剧场免费在线观看| 日韩久久电影| 欧美精品成人91久久久久久久| 天堂网视频在线| 国产亚洲激情| 538国产精品一区二区免费视频| 亚洲中文字幕无码爆乳av | 青青在线视频一区二区三区| 国产理论片在线观看| 免播放器亚洲一区| 国产一区二区免费在线观看| 欧美一级性视频| 中文字幕在线视频一区| 亚洲成人自拍视频| 永久av在线| 综合久久一区二区三区| 久久久999视频| 亚洲综合色婷婷在线观看| 在线看福利67194| 少妇一级淫片免费放中国| 国产综合色在线| 爽爽爽在线观看| 九九精品免费视频| 一区二区三区国产盗摄| 欧美激情乱人伦一区| av手机天堂网| 91在线视频18| 久久免费视频1| 久蕉在线视频| 亚洲h在线观看| 国产极品尤物在线| 黄色片免费在线观看| 亚洲欧美一区二区三区极速播放| 免费日韩视频在线观看| 国产日韩三级| 亚洲免费电影在线观看| 日韩人妻无码一区二区三区| 欧美日本亚洲韩国国产| 久久免费观看视频| 国产无遮挡呻吟娇喘视频| 国产成人免费xxxxxxxx| 自拍偷拍视频在线| 岛国毛片av在线| 一本久道中文字幕精品亚洲嫩| 四季av一区二区| 亚洲涩涩av| 91精品国产免费久久久久久 | 国产精品免费不| 色妞欧美日韩在线| 久久久久久免费观看| 国产尤物一区二区在线| 欧美亚洲视频一区| 国产精品一区二区三区av| 亚洲精品一区在线观看| 国产精品第七页| 久久五月天小说| 国产精品网站入口| 成人免费观看在线视频| 久久久久久久久免费| 好色先生视频污| 国模大尺度视频一区二区| 日韩精品一区二区三区在线| 99视频只有精品| 美女诱惑一区| 欧美一区亚洲二区| 成人在线免费电影网站| 亚洲高清一二三区| 日韩 欧美 中文| 国产人久久人人人人爽| 天天综合网久久| 欧美激情精品久久久六区热门| 国产精品有限公司| 唐人社导航福利精品| 日韩午夜电影在线观看| 国产污视频在线看| 国产尤物一区二区| 国产a级片网站| 亚洲免费资源| 亚洲女人被黑人巨大进入al| 久久久久99精品成人片我成大片| 欧美国产综合色视频| 巨乳女教师的诱惑| 97国产精品| 国产超碰91| av网站免费在线观看| 日韩精品一区二区三区中文不卡| 日韩欧美成人一区二区三区| 国产精品美女久久久久久久| 午夜肉伦伦影院| 久久成人综合| 国外成人免费视频| 日本a人精品| 在线性视频日韩欧美| 国产高中女学生第一次| 日韩欧中文字幕| 国产成人无码aa精品一区| 久久午夜老司机| 亚洲 高清 成人 动漫| 青青草国产免费一区二区下载| 99免费在线观看视频| 99福利在线| 亚洲三级av在线| 久草视频一区二区| 一区二区三区在线视频播放| 在线观看福利片| 国产成人午夜片在线观看高清观看| 人妻有码中文字幕| 欧美二区视频| 亚洲精品高清视频| 亚洲精品中文字幕99999| 91手机在线播放| 性欧美猛交videos| 日韩欧美国产精品一区| 亚洲精品无码久久久久| 天天色天天爱天天射综合| 久久人人爽人人爽人人片| 亚洲中字在线| 91午夜在线观看| 五月久久久综合一区二区小说| 欧美成人蜜桃| 国产一区二区主播在线| 亚洲一品av免费观看| 欧美日韩在线视频播放| 午夜av区久久| 久久免费少妇高潮99精品| 亚洲欧洲成人精品av97| 日韩中文字幕有码| 久久99久久99| 中文字幕一区二区三区四区在线视频| 一区二区三区导航| 国产精品无码免费专区午夜| 国产一级成人av| 亚洲自拍偷拍色片视频| 国产麻豆一区二区三区| 成人欧美一区二区三区在线湿哒哒| 国产最新在线| 色婷婷综合久久久久中文字幕1| 日韩av免费观影| 日韩大陆毛片av| 手机av在线免费观看| 日韩精品一区二区三区四区视频| 精品免费久久久| 福利精品视频在线| 亚洲一二三精品| 国产毛片一区二区| 国产乱子夫妻xx黑人xyx真爽| 亚洲日本激情| 亚洲韩国在线| 成人嫩草影院| 一区二区三区视频| 国产精品99久久免费观看| av日韩免费电影| 国产精品久久久网站| 好吊色欧美一区二区三区四区 | 欧美日本国产视频| 动漫精品一区一码二码三码四码| 亚洲免费观看在线观看| 国产盗摄一区二区三区在线| 亚洲另类一区二区| 欧美亚洲天堂网| 中文字幕在线免费不卡| 黄色精品视频在线观看| 一区二区成人在线视频| 国产午夜精品无码一区二区| 亚洲不卡在线观看| 西西44rtwww国产精品| 欧美午夜久久久| 男女羞羞免费视频| 亚洲国产一区二区三区| 2017亚洲天堂| 久久一留热品黄| 一道本在线观看| 99久久精品国产导航| 国产高清自拍视频| 中文字幕va一区二区三区| 亚洲精品久久一区二区三区777| 免费观看在线综合色| 激情文学亚洲色图| 波多野结衣中文字幕一区二区三区| 精品无码人妻一区| 亚洲欧洲国产日本综合| 日韩污视频在线观看| 欧美丝袜丝nylons| 精品人妻一区二区三区浪潮在线 | 亚洲大片精品永久免费| 美国一级片在线观看| 一区二区三区不卡视频| 欧美一区二区三区网站| 8v天堂国产在线一区二区| 综合久久中文字幕| 日韩欧美激情四射| 成人在线免费公开观看视频| 免费成人高清视频| 国产调教视频在线观看| 97国产在线观看| 欧美性生活一级| 久久99九九| 亚洲精品国产成人影院| 中文字幕一区二区三区乱码 | av在线日韩| 538国产精品一区二区免费视频| 国产91欧美| 激情小说综合网| 中文字幕一区二区三区在线视频| 亚洲自拍偷拍二区| 亚洲深爱激情| 中文字幕一区二区三区人妻在线视频 | 一区二区三区色| 亚洲精品一区二三区| 亚洲二区中文字幕| 182tv在线播放| 国产精品视频在线观看| 丝袜久久网站| 免费h精品视频在线播放| 一区二区三区四区日韩| 在线观看av日韩| 丁香婷婷综合激情五月色| 少妇精品无码一区二区三区| av高清久久久| 欧美高清性xxxx| 亚洲激情在线播放| 在线免费一级片| 欧美一区二区三区视频| 国产在线播放av| 欧美亚洲在线观看| 波多野结衣在线一区二区| 欧美日韩一区二区三区电影| 欧美a级理论片| 国产肥白大熟妇bbbb视频| 欧美日韩国产丝袜美女| 神马久久久久久久久久| 欧美激情18p| 亚洲综合网站| 久久人人爽人人爽人人av| 国产成人精品www牛牛影视| 国产福利视频网站| 欧美猛男gaygay网站| 永久免费av片在线观看全网站| 国产精品日韩精品| youjizzjizz亚洲| www国产免费| 免费精品视频| 国产精品无码永久免费不卡| 五月激情综合婷婷| 人操人视频在线观看| 青青久久av北条麻妃黑人| 免费观看不卡av| 亚洲成人动漫在线| 黄页视频在线91| 国产高潮国产高潮久久久91 | 欧美在线精品一区二区三区| 欧美激情一区二区三区成人| 国产乱人伦丫前精品视频| 无码专区aaaaaa免费视频| 99riav一区二区三区| 亚洲不卡在线视频| 中文字幕欧美在线| www一区二区三区| 国产免费一区二区视频| 99久久99久久精品免费看蜜桃| 亚洲黄色激情视频| 中文字幕亚洲一区在线观看| 99精品在线免费观看| 国产精品久久国产| 91视频xxxx| 中文字幕日韩三级| 色中色综合影院手机版在线观看| 成人开心激情| 亚洲午夜激情| 福利一区二区在线| 日韩综合在线观看| 久久九九全国免费精品观看| 亚洲精品18| 女性隐私黄www网站视频| 高清在线不卡av| 国产性xxxx高清| 在线观看国产欧美| 国产乱码精品一区二区三区亚洲人 | 日韩在线视屏| 天堂va欧美va亚洲va老司机| 天天色天天操综合| jizz在线观看| 国产超碰91| 日本强好片久久久久久aaa| 波多野结衣加勒比| 欧洲国内综合视频| 麻豆影视在线| 欧美伊久线香蕉线新在线| 青青草原综合久久大伊人精品 | 成人激情视频网站| 国产无遮挡又黄又爽又色视频| 欧美丰满老妇厨房牲生活 | 亚洲国产成人精品激情在线| 在线国产精品视频| 国产精品极品|