JMockit 学习笔记

JMockit 是一个针对 Java 的模拟测试框架,主要功能是在单元测试中模拟类/对象的行为。

👉 所有文章
基础 JMockit 入门 JMockit 配置和运行环境
MockUp JMockit : 使用 MockUp mock 函数行为 JMockit : 使用 MockUp 的 tearDown 恢复函数行为 JMockit : 在 MockUp 中使用 Invocation 调用原始逻辑 JMockit : 使用 MockUp mock 私有函数 JMockit : 使用 MockUp mock 构造函数和静态代码块
Expectations JMockit : 使用 Expectations 录制函数行为 JMockit : 使用 Expectations 录制函数每次调用的返回值不同 JMockit : Expectations 生效范围 Jmockit : Expectations 通过 Delegate 定制返回值 JMockit : 使用 Expectations 时候如何进行参数匹配
Verifications JMockit : 使用 Verifications 验证发生过哪些操作 JMockit : 在 Verifications 中使用 withCapture 捕获参数
mock 接口 JMockit : mock 接口 JMockit : mock dubbo 接口
其他 JMockit : NonStrictExpectations Jmockit : Deencapsulation

JMockit 入门


本文示例在 Java 8 中测试通过。

引入依赖

jmockit 的最新版本,必须要指定 -javaagent ,这对一些IDE并不友好。比如在 Intellij IDEA 中无法直接使用右键菜单运行测试类。

如果使用 gradle 构建项目,在 build.gradle 中增加以下配置:

dependencies {

    testCompile group: 'junit', name: 'junit', version: '4.12'
    testCompile "org.jmockit:jmockit:1.46"

}

test {
    jvmArgs "-javaagent:${classpath.find { it.name.contains("jmockit") }.absolutePath}"

    testLogging {
        outputs.upToDateWhen {false}
        showStandardStreams = true
    }

}

使用 Expectations 给返回值打桩

package demo;

import mockit.*;
import org.junit.Test;

import java.util.Random;

public class MyJMockitoDemo {

    @Mocked
    Random mockRandom;

    @Test
    public void test01() {
        System.out.println("----test01----");
        System.out.println(mockRandom.nextInt());

        // 指明调用 nextInt 时,返回 123
        new Expectations() {{      // 通过双大括号构造匿名类,并初始化对象
            mockRandom.nextInt(); result = 123;
        }};

        System.out.println(mockRandom.nextInt());
    }

    @Test
    public void test02() {
        System.out.println("----test02----");
        System.out.println(mockRandom.nextInt());
    }

}

在命令行中执行gradle test,效果如下::

$ gradle test

> Task :test

demo.MyJMockitoDemo > test01 STANDARD_OUT
    ----test01----
    0
    123

demo.MyJMockitoDemo > test02 STANDARD_OUT
    ----test02----
    0

关于双大括号,可以参考 Java 匿名类双大括号初始化

使用 MockUp 给返回值打桩

package demo;

import mockit.*;
import org.junit.Test;

import java.util.Random;

public class MyJMockitoDemo {

    @Test
    public void test01() {
        System.out.println("----test01----");

        Random random = new Random();
        System.out.println(random.nextInt());   // 输出一个随机数

        new MockUp<Random>() {
            @Mock
            public int nextInt() {
                return 1;
            }
        };

        System.out.println(random.nextInt());   // 输出 1
    }

    @Test
    public void test02() {
        System.out.println("----test02----");
        Random random = new Random();
        System.out.println(random.nextInt());   // 输出一个随机数
    }


}

在命令行中执行gradle test,效果如下:

$ gradle test

> Task :test

demo.MyJMockitoDemo > test01 STANDARD_OUT
    ----test01----
    -377985168
    1

demo.MyJMockitoDemo > test02 STANDARD_OUT
    ----test02----
    1201440410

MockUp 可以给静态方法打桩

Calculate 类中增加静态方法 add :

package demo;

public class Calculate {

    // 注意,这是一个 static 函数
    public static int add(int a, int b) {
        return a+b;
    }

}

测试类代码:

package demo;

import mockit.*;
import org.junit.Test;

public class MyJMockitoDemo {

    @Test
    public void test() {

        new MockUp<Calculate>() {
            @Mock
            public int add(int a, int b) {        // 这里不用 static 修饰函数
                return 100;
            }
        };

        System.out.println(Calculate.add(1, 2));  // 输出 100
    }

}

在命令行中执行gradle test,效果如下:

$ gradle test

> Task :test

demo.MyJMockitoDemo > test01 STANDARD_OUT
    100

原理

通过 javaagent 机制,修改被测试类的字节码。


( 本文完 )

文章目录