1 概述
使用jmockit的目的,在于剥离代码间的依赖
比如A方法引用B方法,B方法读取数据库返回一条记录,此时要测试A方法,需要保证B方法正常,不仅要搭建数据库环境,还要配置连接参数,还要在数据库中准备测试数据;而且运行失败并不能直接确定是A方法的问题,可能是B方法错误,或者数据库异常
如果使用jmockit模拟B方法,便省去一系列的麻烦,安心地测A方法即可
2 基本场景
下面使用jmockit模拟static方法、普通方法、私有方法等
public class App {
public static String static_method() {
return "static method";
}
public String normal_method() {
return "normal method";
}
public final String final_method() {
return "final method";
}
private String private_method() {
return "private method";
}
@Test
public void testApp() {
App app = new App();
new Expectations(App.class) {
{
App.static_method();
result = "static method has been mocked";
app.normal_method();
result = "normal method has been mocked";
app.final_method();
result = "final method has been mocked";
}
};
new MockUp<App>(App.class) {
@Mock
String private_method() {
return "private method has been mocked";
}
};
System.out.println(App.static_method());
System.out.println(app.normal_method());
System.out.println(app.final_method());
System.out.println(app.private_method());
}
}
-------------------
static method has been mocked
normal method has been mocked
final method has been mocked
private method has been mocked
3 带参数的方法
3-1 指定相同实参
当方法含有参数时,可以在mock过程中传入相同参数
public class App {
public String say(String name) {
return "Hello " + name;
}
@Test
public void testApp() {
App app = new App();
new Expectations(App.class) {
{
app.say("Mark");
result = "Hello World";
}
};
System.out.println(app.say("Mark")); // Hello World
System.out.println(app.say("Jack")); // Hello Jack
}
}
3-2 万能参数
如果想mock任意实参,可能使用万能参数any
可供组合的类型还有anyString, anyInt, anyBoolean, anyFloat等,表示任意该类型数据
public class App {
public String say(String name) {
return "Hello " + name;
}
@Test
public void testApp() {
App app = new App();
new Expectations(App.class) {
{
app.say(anyString);
result = "Hello World";
}
};
System.out.println(app.say("Mark")); // Hello World
System.out.println(app.say("Jack")); // Hello World
}
}
3-3 根据参数决定结果
如果想根据不同的参数,返回不同的结果,可以使用Delegate类,附加一个自定义方法,方法名不一定非得delegate,随意指定
public class App {
public String say(String name) {
return "Hello " + name;
}
@Test
public void testApp() {
App app = new App();
new Expectations(App.class) {
{
app.say(anyString);
result = new Delegate() {
String delegate(String name) {
if (name.length() > 5) {
return "Hello World";
} else {
return "Goodbye";
}
}
};
}
};
System.out.println(app.say("Mark")); //Goodbye
System.out.println(app.say("Sophia")); //Hello World
}
}
3-4 部分参数mock,其他按原方法调用
这里我们使用了MockUp<> 和 @Mock组合,并且在mock方法中加了一个新的对象invocation
invocation.proceed方法,负责对原始方法的调用
public class App {
public String say(String name) {
return "Hello " + name;
}
@Test
public void testApp() {
App app = new App();
new MockUp<App>(App.class) {
@Mock
String say(Invocation invocation, String name) {
if (name.length() > 5) {
return "Hello World";
}
return invocation.proceed(name);
}
};
System.out.println(app.say("Mark")); // Hello Mark
System.out.println(app.say("Jack")); // Hello Jack
System.out.println(app.say("Sophia")); // Hello World
}
}
4 Mock clinit/init初始化
有时静态块,或者类的构造函数内有外部依赖的初始化操作,使用下面的方法实现mock
public class App {
public static int count = 1;
static {
count += 10;
}
public App() {
count += 100;
}
}
----------------
public class AppTest {
@Test
public void testApp() {
new MockUp<App>(App.class) {
@Mock
void $clinit() {}
@Mock
void $init() {}
};
App app = new App();
System.out.println(App.count); // 0
}
}
网友评论