使用Mock Framework 是單元測試重要的一環,可以讓測試碼更簡潔、易讀。現在 Android 最主流的Mock Framework 就是 mockito 了,接下來將介紹如何使用。


開始使用

1. Building with Gradle

在 app 的 build.gradle 加入:

dependencies {
    ...
    testCompile('org.mockito:mockito-core:1.10.19')
    ...
}

2. Test code with Mockito

現在讓我們來增加 MyMath 的需求,在 MyMath 裡加入Logger。當計算的結果小於0時,Logger會紀錄一次。現在就用 Mockito 來完成這需求的測試案例。

首先,改寫一下原來的MyMath 程式:

public class MyMath {

    private Logger logger;

    public MyMath(Logger logger){
        this.logger = logger;
    }

    public int add(int first, int second){
        int sum = first + second;
        if(sum < 0)
            logger.log(String.valueOf(sum));
        return first + second;
    }
}
public class Logger {

    public void log(String message){
        //DO WHATEVER YOU WANT
    }
}

要如何驗證Logger是否有被呼叫呢?這時候就是要使用 Mockito 了。在MyMathTest中新增一條測試案例:

    //@Mock 代表要讓這物件有 mock 的行為
    @Mock
    private Logger mockLogger = new Logger();

    @Test
    public void sample_log_call_once(){
        //arrange
        //要先呼叫initMocks,才能使mock的物件正常運作
        MockitoAnnotations.initMocks(this);


        //act
        //在這裡預期logger會被呼叫一次
        MyMath myMath = new MyMath(mockLogger);
        myMath.add(-1, -2);

        //assert
        //verify 相當於之前的 assert,這裡的意思是要驗證 mockLogger 這個物件
        //的某個 method 是否被呼叫一次,在這個例子中是 log 這個 method,並且不
        //需要在意參數的字串是甚麼(Mockito.anyString())
        Mockito.verify(mockLogger).log(Mockito.anyString());    
    }

3. 執行測試

這次也不意外的驗證通過了,下面再舉幾個例子來說明 Mock Framework 的強大之處。

4. 驗證被呼叫多次

在正常的使用情境下,同一個 method 有可能被呼叫多次,使用 Mockito 能夠很簡單的驗證這種測試案例

    @Test
    public void sample_logger_call_three_times(){
        MockitoAnnotations.initMocks(this);

        int expectCallTimes = 3;

        MyMath myMath = new MyMath(mockLogger);
        myMath.add(-1, 2);
        myMath.add(1, -2);
        myMath.add(3, 100);
        myMath.add(0, -2);
        myMath.add(-999, 33);
        myMath.add(-999, 1000);

        //verify 可以指定被呼叫的次數
        Mockito.verify(mockLogger, Mockito.times(expectCallTimes)).log(Mockito.anyString());
    }

一樣的執行測試 - > 通過測試。

results matching ""

    No results matching ""