JMockit 入门


#Java 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 机制,修改被测试类的字节码。


( 本文完 )