本文示例在 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 机制,修改被测试类的字节码。