介绍
使用 Expectations 录制函数行为,然后通过实际的单测逻辑重放录制的函数行为。
示例
被测试类
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 org.junit.Test;
public class CalculatorTest {
@Test
public void test_add_01() {
Calculator calculator = new Calculator();
new Expectations(Calculator.class) {{
// 当参数分别是 1、2 时,返回1
calculator.add(1, 2); result = 1;
}};
System.out.println(calculator.add(1, 2));
System.out.println(calculator.add(2, 2));
}
}
执行结果:
1
4
另外一种写法是用 withEqual
匹配参数精确值:
package demo;
import mockit.Expectations;
import org.junit.Test;
public class CalculatorTest {
@Test
public void test_add_01() {
Calculator calculator = new Calculator();
new Expectations(Calculator.class) {{
// 当参数分别是 1、2 时,返回1
calculator.add(withEqual(1), withEqual(2)); result = 1;
}};
System.out.println(calculator.add(1, 2));
System.out.println(calculator.add(2, 2));
}
}
类似 withEqual 的方法还有很多,可以跳转到源代码查看。
示例:不同单测之间的 mock 是隔离的
package demo;
import mockit.Expectations;
import org.junit.Test;
public class CalculatorTest {
@Test
public void test_add_01() {
System.out.println("--- test_add_01 ---");
Calculator calculator = new Calculator();
new Expectations(Calculator.class) {{
// 当参数分别是 1、2 时,返回1
calculator.add(1, 2); result = 1;
}};
System.out.println(calculator.add(1, 2));
System.out.println(calculator.add(2, 2));
}
@Test
public void test_add_02() {
System.out.println("--- test_add_02 ---");
System.out.println(Calculator.staticAdd(1, 2)); // 不会被 test_add_01 的mock影响到
}
}
执行结果:
--- test_add_01 ---
1
4
--- test_add_02 ---
3
示例:任意参数,返回特定值
package demo;
import mockit.Expectations;
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;
}};
System.out.println(calculator.add(1, 2));
System.out.println(calculator.add(2, 2));
}
}
执行结果:
1
1
注意:
anyInt 的定义是 @Nonnull protected final Integer anyInt = 0;
,但是上面的 Expectations 如果改成:
new Expectations(Calculator.class) {{
calculator.add(0, 0); result = 1;
}};
执行结果会变成:
3
4
Missing 1 invocation to:
demo.Calculator#add(0, 0)
on mock instance: demo.Calculator@532f2596
这意味着 anyInt 与 0 不等价。为什么?以后探索。
另外,默认情况下 Expectations 录制的函数,必须被执行一次,否则会报错 Missing 1 invocation to:
之类的错误。
示例:录制后,不重放,也不报错
指定 minTimes
为 0 即可。相关的变量还有 times
、maxTimes
。
package demo;
import mockit.Expectations;
import org.junit.Test;
public class CalculatorTest {
// 会报错
@Test
public void test_add_01() {
Calculator calculator = new Calculator();
new Expectations(Calculator.class) {{
calculator.add(1, 2); result = 1;
}};
}
}
执行时会报错:
Missing 1 invocation to:
demo.Calculator#add(1, 2)
......
因为 minTimes 默认为 1。
将 minTimes 设置为 0,则不会报错:
package demo;
import mockit.Expectations;
import org.junit.Test;
public class CalculatorTest {
// 不会报错
@Test
public void test_add_01() {
Calculator calculator = new Calculator();
new Expectations(Calculator.class) {{
calculator.add(1, 2); result = 1; minTimes = 0;
}};
}
}
执行后不会报错。
示例:让函数什么都不做
package demo;
import mockit.Expectations;
import org.junit.Test;
public class CalculatorTest {
@Test
public void test_add_01() {
Calculator calculator = new Calculator();
new Expectations(Calculator.class) {{
calculator.noop();
}};
calculator.noop(); // 执行时不会输出内容
}
}
示例:让函数抛异常
让 result 的值是一个异常类即可。
package demo;
import mockit.Expectations;
import org.junit.Test;
public class CalculatorTest {
@Test
public void test_add_01() {
Calculator calculator = new Calculator();
new Expectations(Calculator.class) {{
calculator.noop(); result = new RuntimeException("异常");
}};
calculator.noop();
}
}
执行结果:
异常
java.lang.RuntimeException: 异常
at demo.CalculatorTest.test_add_01(CalculatorTest.java:16)
at java.base/java.lang.Thread.run(Thread.java:829)
示例:同一个类,不同对象,分别录制
new Expectations(Calculator.class) {{
// 当参数分别是 1、2 时,返回1
calculator.add(1, 2); result = 1;
}};
上面这种方式是针对 Calculator 的所有对象。
如果要不同对象,分别录制,则:
package demo;
import mockit.Expectations;
import org.junit.Test;
public class CalculatorTest {
@Test
public void test_add_01() {
Calculator calculator01 = new Calculator();
Calculator calculator02 = new Calculator();
new Expectations(calculator01, calculator02) {{
calculator01.add(1, 2); result = 100;
calculator02.add(1, 2); result = 200;
}};
System.out.println(calculator01.add(1, 2));
System.out.println(calculator02.add(1, 2));
}
}
执行结果:
100
200
示例:录制静态函数行为
package demo;
import mockit.Expectations;
import org.junit.Test;
public class CalculatorTest {
@Test
public void test_add_01() {
new Expectations(Calculator.class) {{
Calculator.staticAdd(1, 2); result = 1;
}};
System.out.println(Calculator.staticAdd(1, 2));
}
}
执行结果:
1
示例:同一函数每次返回的结果不一样
package demo;
import mockit.Expectations;
import org.junit.Test;
public class CalculatorTest {
@Test
public void test_add_01() {
new Expectations(Calculator.class) {{
Calculator.staticAdd(1, 2);
result = 1; // 第1次调用时返回1
result = 2; // 第2次,以及之后的调用返回1
}};
System.out.println(Calculator.staticAdd(1, 2));
System.out.println(Calculator.staticAdd(1, 2));
System.out.println(Calculator.staticAdd(1, 2));
}
}
执行结果:
1
2
2
另外一种方式是,返回数组:
package demo;
import mockit.Expectations;
import org.junit.Test;
public class CalculatorTest {
@Test
public void test_add_01() {
new Expectations(Calculator.class) {{
Calculator.staticAdd(1, 2);
result = new int[] {1, 2};
}};
System.out.println(Calculator.staticAdd(1, 2));
System.out.println(Calculator.staticAdd(1, 2));
System.out.println(Calculator.staticAdd(1, 2));
}
}