JMockit:使用 Verifications 验证发生过哪些操作


#Java Jmockit#


介绍

Verifications 一般放在单元测试的结尾处,用于验证发生过哪些操作。写法和 Expectations 很像,但不需要指定 result。

和 Expectations 搭配使用。Expectations 在前,Verifications 在后。

测试示例

被测试类:

package demo;

public class Calculator {

    // 非静态函数
    public int add(int a, int b) {
        return a+b;
    }

    // 静态函数
    public static int staticAdd(int a, int b) {
        return a+b;
    }

    // 空函数
    public void noop() {
        System.out.println("没有被 mock");
    }

}

示例: 指定参数调用发生了有且一次

正例:

package demo;

import mockit.Expectations;
import mockit.Verifications;
import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {

    @Test
    public void test_add_01() {
        Calculator calculator = new Calculator();

        // 录制
        new Expectations(Calculator.class) {{
            calculator.add(anyInt, anyInt); result = 1;
        }};

        // 重放(执行)
        int addResult = calculator.add(1, 2);
        Assert.assertEquals(1, addResult);

        // 验证
        new Verifications() {{
            calculator.add(1, 2); times = 1;
        }};
    }

}

执行不报错。

反例:

package demo;

import mockit.Expectations;
import mockit.Verifications;
import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {

    @Test
    public void test_add_01() {
        Calculator calculator = new Calculator();

        // 录制
        new Expectations(Calculator.class) {{
            calculator.add(anyInt, anyInt); result = 1;
        }};

        // 重放(执行)
        int addResult = calculator.add(1, 2);  // 第1次调用
        Assert.assertEquals(1, addResult);

        calculator.add(1, 2);   // 第2次调用

        // 验证  会报错
        new Verifications() {{
            calculator.add(1, 2); times = 1;
        }};
    }

}

重放时,调用了两次 add(1, 2) ,验证时希望是1次,所以会报错:

1 unexpected invocation to:
demo.Calculator#add(1, 2)
   on mock instance: demo.Calculator@1a539064

示例: 使用参数匹配

package demo;

import mockit.Expectations;
import mockit.Verifications;
import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {

    @Test
    public void test_add_01() {
        Calculator calculator = new Calculator();

        // 录制
        new Expectations(Calculator.class) {{
            calculator.add(anyInt, anyInt); result = 1;
        }};

        calculator.add(1, 2);
        calculator.add(2, 2);

        // 验证
        new Verifications() {{
            calculator.add(anyInt, anyInt); times = 2;
        }};
    }

}

示例:使用 minTimes 指定最小执行次数

package demo;

import mockit.Expectations;
import mockit.Verifications;
import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {

    @Test
    public void test_add_01() {
        Calculator calculator = new Calculator();

        // 录制
        new Expectations(Calculator.class) {{
            calculator.add(anyInt, anyInt); result = 1;
        }};

        calculator.add(1, 2);
        calculator.add(2, 2);

        // 验证
        new Verifications() {{
            calculator.add(anyInt, anyInt); minTimes = 1;
        }};
    }

}

示例:使用 maxTimes 指定最大执行次数

package demo;

import mockit.Expectations;
import mockit.Verifications;
import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {

    @Test
    public void test_add_01() {
        Calculator calculator = new Calculator();

        // 录制
        new Expectations(Calculator.class) {{
            calculator.add(anyInt, anyInt); result = 1;
        }};

        calculator.add(1, 2);
        calculator.add(2, 2);

        // 验证
        new Verifications() {{
            calculator.add(anyInt, anyInt); maxTimes = 10;
        }};
    }

}

示例:多条验证

package demo;

import mockit.Expectations;
import mockit.Verifications;
import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {

    @Test
    public void test_add_01() {
        Calculator calculator = new Calculator();

        // 录制
        new Expectations(Calculator.class) {{
            calculator.add(anyInt, anyInt); result = 1;
        }};

        calculator.add(1, 2);
        calculator.add(2, 2);

        // 验证
        new Verifications() {{
            calculator.add(1, 2); times = 1;
            calculator.add(1, 2); times = 1;
            calculator.add(1, 2); times = 1;
            calculator.add(anyInt, anyInt); times = 2;
        }};
    }

}

示例:若函数行为未被录制,则验证不会报错

package demo;

import mockit.Expectations;
import mockit.Verifications;
import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {

    @Test
    public void test_add_01() {
        Calculator calculator = new Calculator();

        // // 录制
        // new Expectations(Calculator.class) {{
        //     calculator.add(anyInt, anyInt); result = 1;
        // }};

        // 执行
        int addResult = calculator.add(1, 2);
        Assert.assertEquals(3, addResult);

        // 验证
        new Verifications() {{
            calculator.add(1, 2); times = 2;
        }};
    }

}

不会报错。

示例:验证对于 MockUp 无效

package demo;

import mockit.Expectations;
import mockit.Mock;
import mockit.MockUp;
import mockit.Verifications;
import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {

    @Test
    public void test_add_01() {
        Calculator calculator = new Calculator();

        new MockUp<Calculator>() {
            @Mock
            public int add(int a, int b) {
                return 1;
            }
        };

        // 执行
        int addResult = calculator.add(1, 2);
        Assert.assertEquals(1, addResult);

        // 验证
        new Verifications() {{
            calculator.add(1, 2); times = 2;
        }};
    }

}

( 本文完 )