Heng Lin

  • 主頁
  • 所有文章
搜尋文章 關於我

Heng Lin

  • 主頁
  • 所有文章

Java Unit Test 使用 Mockito + Powermock (3)

2020-08-29

離上一篇文已經間隔兩個月,今天終於有些動力來補充 Unit Test
今天要聊的是 ArgumentCaptor

在許多的情況下,我們只 assert 最終的結果 (Output)
但在整個測試的過程中有參數經過不同 method 傳遞,一不小心或粗心可能在某一層變更到數值
導致錯誤的輸入 (Input) 往下傳遞,而這個錯誤有可能不會影響最終的結果
就像一顆未爆彈潛伏在程式內,很難在短時間內發現…但未來可能在某個版本上爆發

所以我們要避免掉這個問題,會在比較重要的節點上
先驗證此時傳入到 method 的參數與我們預期的相符合

ArgumentCaptor 可以幫助我們取得執行過程中所傳遞的參數
它的用法很簡單,只需要定義與輸入參數相同類型
之後在 verify(...).callMethod(captor.capture()) 的時候,放入目標 method 中
就可以取得當下傳入的參數值,接下來就可以針對輸入內容進行 assert

1
2
3
4
5
6
7
ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class);

...

Mockito.verify(...).callMethod(captor.capture());
Argument actual = captor.getValue();
assertThat(expected, actual)

在此使用之前做的 WebController 進行修改
先在 WebDao 增加 updateData 的 method 傳入 Data

1
2
3
4
5
6
7
8
public class WebDao {

...

public Optional<Data> updateData(Data data) throws DatabaseException {
throw new DatabaseException();
}
}

之後我們就可以在測試期間,使用 ArgumentCaptor 來取得當時傳入的資料


WebController 也要增加一個 update() 讓我們進行更新資料的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class WebController {

...

public String update(HttpServletRequest request){
int id = Integer.parseInt(request.getParameter("id"));
String col1 = request.getParameter("col1");
String col2 = request.getParameter("col2");
Optional<Data> data;
try {
data = webDao.updateData(new Data(id, col1, col2));
} catch (DatabaseException e) {
return e.getMessage();
}
return GSON.toJson(data.get());
}
}

最後在 WebControllerTest 新增一個測試,用於測試資料的更新結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class WebControllerTest {
@Test
public void Should_GetChangeData_When_UpdateDataValue() throws DatabaseException {
final int ID = 1;
final String ORI_COL1 = "col1";
final String ORI_COL2 = "col2";

final String NEW_COL1 = "new col1";
final String NEW_COL2 = "new col2";

// given
Optional<Data> newData = Optional.of(new Data(ID, NEW_COL1, NEW_COL2));
ArgumentCaptor<Data> dataCaptor = ArgumentCaptor.forClass(Data.class);

when(this.request.getParameter("id")).thenReturn(String.valueOf(ID));
when(this.request.getParameter("col1")).thenReturn(ORI_COL1);
when(this.request.getParameter("col2")).thenReturn(ORI_COL2);
when(this.webDao.updateData(any())).thenReturn(newData);

// when
String response = this.webController.update(this.request);

// then
try{
Data result = this.GSON.fromJson(response, Data.class);

verify(this.webDao, times(1)).updateData(dataCaptor.capture());

Data inputData = dataCaptor.getValue();
assertThat(ID, is(inputData.getId()));
assertThat(ORI_COL1, is(inputData.getCol1()));
assertThat(ORI_COL2, is(inputData.getCol2()));

assertThat(result.getId(), is(ID));
assertThat(result.getCol1(), is(NEW_COL1));
assertThat(result.getCol2(), is(NEW_COL2));
} catch (JsonSyntaxException e){
fail("parser response data fail.");
}
}
}

第 13 行,我們定義了 ArgumentCaptor 用來裝 Data 類型的資料
第 27 行, verify updateData 的時候,使用 dataCaptor.capture() 取得輸入的 Data
第 29~32 行,驗證輸入的參數與我們預期的相同


後話

隨著時間推移,程式開發到一個階段,程式碼也逐漸積累量到一定的規模
有時候修改一個小地方,可能會導致其他地方也受到影響
此時如果沒有強健的測試預防開發者手殘,等到 release 後…
真的不敢想像…

最近工作上常常有機會寫到許多測試
瞭解到測試的重要性,這也是我這幾個月寫測試的感悟…

  • unit test

扫一扫,分享到微信

微信分享二维码
JCConf 2020
Java Unit Test 使用 Mockito + Powermock (2)
© 2020 Heng Lin
Hexo Theme Yilia by Litten
  • 搜尋文章
  • 關於我

tag:

  • hadoop
  • big data
  • conference
  • java
  • nio
  • thread
  • unit test
  • shell
  • gradle
  • docker
  • spring cloud
  • android
  • memory leak
  • math
  • hexo
  • Blog
  • probability
  • statistics
  • clean code
  • illustrator
  • js

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • JCConf 2020

    2020-11-28

    #conference

  • Java Unit Test 使用 Mockito + Powermock (3)

    2020-08-29

    #unit test

  • Java Unit Test 使用 Mockito + Powermock (2)

    2020-06-14

    #unit test

  • Java Unit Test 使用 Mockito + Powermock (1)

    2020-04-25

    #unit test

  • 關於 Java CompletableFuture 的用法

    2020-04-19

    #java#thread

  • Java NIO ByteBuffer 基本操作圖

    2020-01-13

    #java#nio

  • 對於 Java Fork Join framework 的理解

    2020-01-07

    #java#thread

  • Java BlockingQueue 適合應用在哪些場景

    2020-01-06

    #java#thread

  • 對於 Java ThreadPoolExecutor 的理解

    2020-01-05

    #java#thread

  • Java ReentrantLock 和 ReentrantReadWriteLock 的使用時機

    2020-01-04

    #java#thread

  • Java volatile 的使用時機

    2020-01-03

    #java#thread

  • spring cloud 使用 gradle 打包 docker image

    2019-11-11

    #gradle#docker#spring cloud

  • Hadoop RecordReader

    2019-11-06

    #hadoop#big data

  • Hadoop Writable

    2019-11-03

    #hadoop#big data

  • JSDC 2019

    2019-10-26

    #conference

  • 簡易版shell script作自動化處理

    2019-10-22

    #shell

  • JCConf 2019

    2019-10-04

    #conference

  • JCConf 2018

    2018-10-21

    #conference

  • 用illustrator幫自己畫一個新頭像

    2018-07-15

    #illustrator

  • 使用視覺化來解釋數學原理的youtube - 3Blue1Brown

    2018-06-24

    #math

  • 使用 Gradle 自動初始化 Spock

    2018-05-20

    #unit test#gradle

  • 提升Socket傳送Large file的速度

    2018-05-13

    #java

  • 你真的了解Java中的Thread運作嗎? - 容易讓人誤解的synchronized method

    2018-04-29

    #java#thread

  • 從無到有DIY chart (二)

    2018-04-14

    #js

  • 從無到有DIY chart (一)

    2018-04-01

    #js

  • 標準常態分佈的機率密度函數

    2018-03-24

    #math#probability#statistics

  • Linux 如何避免重複執行特定jar

    2018-03-17

    #shell

  • 使用 WeakReference 解決 Android 發生 memory leak 問題

    2018-03-10

    #java#android#memory leak

  • 比較好的nested map寫法

    2018-03-03

    #java#clean code

  • 更換hexo themes

    2018-02-20

    #hexo

  • 第一篇Blog,從SVN到Git

    2018-02-16

    #Blog

全端工程師

60% Java
40% Javascript