Mockito Hello World

聖騎士wind發表於2015-04-10

Mockito Hello World

專案配置

  IDE是Intellij IDEA,用gradle配置專案.
  新建一個Java專案,gradle中需要有這個:
 
repositories { jcenter() }
dependencies { testCompile "org.mockito:mockito-core:1.+" }

 

單元測試用JUnit 4,所以gradle檔案如下:
apply plugin: 'java'
apply plugin: 'idea'

sourceCompatibility = 1.5
version = '1.0'

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
    testCompile "org.mockito:mockito-core:1.8.5"
}

  寫好之後在命令列執行:gradle idea
  相關的包就會下載好,並出現在這裡:
 
 

Hello World程式

  想著寫一個Hello World說明一下Mockito怎麼用,結果寫著寫著就寫複雜了.
  先看程式碼:
package com.mengdd.examples.mockito;

public class HelloWorld {
    private MyRobot mRobot;

    public MyRobot getRobot() {
        return mRobot;
    }

    public void setRobot(MyRobot robot) {
        this.mRobot = robot;
    }

    /**
     * This is the method we want to test.
     * When there is an robot, this method return the robot's information
     * otherwise, return some sorry text
     */
    public String sayHello() {
        MyRobot robot = getRobot();
        if (null != robot) {
            return robot.getSomeInfo();
        }

        return "No robot here, sorry!";
    }

    /**
     * MyRobot class
     */
    public static class MyRobot {

        /**
         * Get some information from somewhere, the implementation may varies
         */
        public String getSomeInfo() {
            return "Hello World -- From robot";
        }
    }
}

  這段程式碼裡面包含了一個HelloWorld類和一個內部靜態類MyRobot(我的機器人).
  HelloWorld中有一個方法叫sayHello(),是我們要測的方法.
  它會判斷成員變數是否為空,不為空則呼叫其方法獲取一些資訊,否則返回一條提示資訊.
 
 
  -------------------
  這裡插播一下,關於內部類的介紹可以參見以前的一篇筆記:http://www.cnblogs.com/mengdd/archive/2013/02/08/2909307.html
  內部靜態類和內部非靜態類可以類比:靜態成員變數和非靜態成員變數.
  -------------------
 
 
  測試類程式碼如下:
package com.mengdd.examples.mockito;

import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;


public class HelloWorldTest {
    @Test
    public void testSayHelloWhenThereIsRobot() throws Exception {
        // We want to test the sayHello() method in the class HelloWorld.
        // But we don't care about how MyRobot get its information.(We can treat it as external interface).

        // Maybe the robot rely on many complicated things.(Although it's simple in this case.)
        // And when the robot's actions change in the future, we don't need to change this test case.

        // We can mock the MyRobot's action to make it simple and just test whether sayHello() can do its own work.


        // Mock steps
        HelloWorld.MyRobot robot = mock(HelloWorld.MyRobot.class); // Mock MyRobot class
        String mockInfo = "some mock info";
        when(robot.getSomeInfo()).thenReturn(mockInfo); // Set behavior for mock object

        // real object
        HelloWorld helloWorld = new HelloWorld();//This is the real objec we want to test
        helloWorld.setRobot(robot);//set the mock robot to real object

        // execute the target method we want to test
        String result = helloWorld.sayHello();

        // assert the result is what we want to have
        assertThat(result, is(mockInfo));
    }
}

  因為我們要測試的是HelloWorld的sayHello()方法是否能正常工作.
  我們需要假定其中robot的行為是正常的(我們並不關心robot實際上做的工作,以及它怎麼做),所以這裡用到了mock.
  比如如果機器人的實現中要傳送一個請求,我們這裡就是直接mock它得到的結果,而不是真的去發這個請求.
 
  就好像準備好了所需要的所有外部條件,看sayHello()方法的表現是否能符合我們的預期.
 
 
  為了全面起見,測試了sayHello()的另一種case,這裡沒有用到mockito.
@Test
public void testSayHelloWhenThereIsNoRobot() throws Exception {
    HelloWorld helloWorld = new HelloWorld();
    helloWorld.setRobot(null);

    String result = helloWorld.sayHello();

    assertThat(result, is("No robot here, sorry!"));
}
 
 

參考資料

  官網: http://mockito.org/
  Mockito at github: https://github.com/mockito/mockito
  可以在這裡看版本號: http://mvnrepository.com/artifact/org.mockito/