mockito的用法

well,說來慚愧,以前一直知道有這麼個東西,但老是看不進去。恰好趁着此次迭代間隙有些閒暇,認真看了下,大概明白是怎麼回事了。apache

首先,mock是個概念,這個詞的本意就是「虛假的」、「模仿的」。在測試的時候,不少狀況下都沒法獲取真正的對象,如Servlet對象,但測試又須要這個對象,怎麼辦?maven

固然是弄個假的給糊弄一下啦。ide

其次,mock的實現有不少,本文只關心Mockito,其餘的請自行百度哈。測試

 

看到全部的資料都說Mockito有兩方面的做用:1. 驗證方法調用; 2. 指定特定條件下某個方法的返回值,或者執行特定的動做。ui

廢話少說,直接上代碼驗證一下。spa

1. 先上pom文件:代理

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>win.larryzeal</groupId>
    <artifactId>mockito-study</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    <dependencies>
        <!--2.x not good 呵呵-->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.10.19</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

 

2. 再提供一個接口 Processor,不提供實現。code

package win.larryzeal.mockito.study;

public interface Processor {
    void process();
    
    int get();
    
    void cb(int a, int b,  Callback cb);
}

package win.larryzeal.mockito.study;

public interface Callback {
    int onSuccess();
    int onFail();
}

 

3. 而後看一下怎麼驗證調用 - 須要特別指出的是,mock的對象至關於加了一層代理,能夠認爲是實現。以下:xml

package win.larryzeal.mockito.study;

import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

//1. 驗證方法調用
public class MockTest {

    @Test
    public void r1() {

        Processor mock = Mockito.mock(Processor.class);
        mock.process();

        //注意,這裏至關於驗證以前的調用!
        Mockito
                .verify(mock) //Alias to verify(mock, times(1))  驗證是否調用一次
                .process();

    }

    @Test
    public void r2() {

        Processor mock = Mockito.mock(Processor.class);
        mock.process();

        //注意,這裏至關於驗證以前的調用!
        Mockito
                .verify(mock, Mockito.times(3)) //Alias to verify(mock, times(1))  驗證是否調用n次
                .process();

    }


}

上面的驗證很簡單,就是驗證指定mock的特定方法的調用 - 能夠是調用次數,也能夠是超時等,還能夠是複合的驗證條件,如Mockito.timeout(1000).times(3)。對象

 

4. 再來看看怎麼定製特定方法的返回結果 - 頗有用噢,特別是針對遠程調用、接口調用等狀況。

package win.larryzeal.mockito.study;

import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

//2. 指定某個方法的返回值
public class MockTest {

    @Test
    public void r3() {

        Processor mock = Mockito.mock(Processor.class);

        //注意,這裏至關於設定mock裏某個方法的返回值!在測試遇到嵌套方法,且嵌套方法不便於調用時,很是有用。
        Mockito
                .when(mock.get()) 
                .thenReturn(0xff); //這裏是可變參數,屢次調用的狀況下,依次返回相應的數值;若是超出次數,返回最後一個值。

        System.out.println(mock.get());
    }

}

嗯嗯,when用於指定調用的方法,thenXxx用於指定返回結果 或者 拋出異常。

 

5. 再來看看回調的狀況 - 傳入的參數是條件,根據條件來調用特定的回調。

package win.larryzeal.mockito.study;

import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;


//2. 指定某個方法的返回值,或者是執行特定的動做
public class MockTest {

    @Test
    public void r4() {
        Processor mock = Mockito.mock(Processor.class);

        //這裏,是設定在特定條件下調用特定的回調! - 這個特定的條件是不一樣的參數,能夠是具體的,也能夠是Mockito.anyXxx。
        Mockito
                .doAnswer((InvocationOnMock invocation) -> {
                    Callback cb = invocation.getArgumentAt(2, Callback.class);
                    cb.onFail();
                    return null; //嗯?這裏的返回值是?
                })
                .when(mock)
                .cb(Mockito.eq(1), Mockito.eq(-1), Mockito.any(Callback.class)); //TODO 若是用matcher,那全部的參數都須要是matcher

        //實際的調用
        mock.cb(1, -1, new Callback() {
            @Override
            public int onSuccess() {
                System.out.println("ok");
                return 200;
            }

            @Override
            public int onFail() {
                System.out.println("fail");
                return 500;
            }
        });
        mock.cb(1, 1, null);
    }

}

前面設定條件,而後實際調用下,就是這麼簡單!

ps:暫時不明白那個Invocation的返回值是幹嗎用的,稍後再說。

 

6. 最後看看 spy,Mockito 除了mock()方法,還提供了spy,簡單的說就是能夠不指定方法的返回值,而是返回類型的默認值(零值)。以下:

package win.larryzeal.mockito.study;

import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public class MockTest {


    @Test
    public void r5() {

        //spy,除非設定,返回返回默認值
        Processor spy = Mockito.spy(Processor.class);

        //屢次調用的狀況下,依次返回相應的數值;若是超出次數,返回最後一個值。
        //Mockito.when(spy.get()).thenReturn(3, 5, 9); //不指定的狀況,返回0

        System.out.println(spy.get());
        System.out.println(spy.get());
        System.out.println(spy.get());
        System.out.println(spy.get());

        //一樣能夠校驗執行次數
//        Mockito.verify(spy).get(); //一次
        Mockito.verify(spy, Mockito.times(4)).get();
    }

}

 

ok,至此基本就算大功告成了,趕快去試試吧?

相關文章
相關標籤/搜索