Jmokit
一:环境搭建:
Jar包加载maven:
<dependency>
<groupId>org.jmockitgroupId>
<artifactId>jmockitartifactId>
<version>1.18version>
dependency>
<dependency>
<groupId>org.jmockitgroupId>
<artifactId>jmockit-coverageartifactId>
<version>1.18version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.8version>
<scope>testscope>
dependency>
gradle :
testCompile("org.jmockit:jmockit:1.30"),
Jmockit.jar包必放在junit.jar包之前,而且junit.jar的版本必须是4.8以上,否则会报错: java.lang.IllegalStateException: JMockit wasn’t properly initialized; check that jmockit.jar precedes junit.jar in the classpath
Mock 简介
Jmockit 整体图
Mock的三个阶段:mock只能mock一次,否则会报错
录制模拟行为:(基于方法返回值)
分为三种:
1:NonStrictExpectations 不限制次数和顺序
2:StrictExpectations 严格限制次数和顺序
3:Expectations 至少调用一次,不要求顺序
new Expectations(Model.class) {
{
Model.getName();
result = "lisi";
Model.getAge();
result = 10;
}
};
调用仿制行为
方法的调用
验证调用
new Verifications() {//验证预期Mock行为被调用
{
app.getName();
times = 1;
app.getAge();
times = 1;
}
};
Mock两种方式:
(app为对象实例)
@Injectable Model app; //只虚拟app这一个对象
新建其他对象的内容不会改变
@Mocked Model app; //模拟所有的Model类
新建其他对象的内容也将会改变
格式:对象.方法
result = expr //调用这个方法是给他赋予期望值
ps: 当expr 为多个时eg(”a”,”b”,”c”),则按照调用顺序一次给值
第一次:a,第二次:b…
例子:
public void test1(){
//录制mock
new Expectations(app) {
{
app = new Model();
app.getName();
result = "lisi"; //调用getName是赋予“list”
app.getAge();
result = 10; //调用getAge是赋予10
}
};
//调用mock
assertThat(10, equalTo(app.getAge()));
assertThat("lisi", equalTo(app.getName()));
//校验mock是否被调用并且校验校验调用次数
new Verifications() {//验证预期Mock行为被调用
{
app.getName();
times = 1;
app.getAge();
times = 1;
}
};
}
—————————-华丽的分割线———————————
以上都是黑盒测试,不管方法内部,只改变返回值
下面说下改变方法内部的实例(基于方法内部行为)
new MockUp() {//使用MockUp修改被测试方法内部逻辑 ,<>中只能为类名
@Mock
public int getAge() {
return 30;
}
};
用mockUp来对类中的方法内部进行改造
被改造的方法需要用@Mock注解
感觉这个方法是最有用的方法,可以模拟几乎任何行要的方法(包括静态、私有)及返回结果
再举个栗子:
*(非接口类型)*
@Tested //DriverService 是正常类
private DriverService driverService;
@Injectable //这里的driverDAO 是driverService的一个属性,@Injectable可以自动关联,DriverDAO是接口
private DriverDAO driverDAO;
@Test
public void testFind() {
//正常类
new MockUp() {
@Mock
public Driver findDriver(String Id){
return new Driver(){{setTimestamp(new DateTime());}};
}
};
//接口类
driverDAO = new MockUp() {
@Mock
public Driver findOne(String Id){
return new Driver(){{setUuid("44444444");}};
}
}.getMockInstance();//需要获取实例
Driver driver = driverService.findDriver("");
Driver Driver = driverDAO.findOne("");
System.out.println(driver);
}
下面再说下Jmockit提供的一些工具API
虚拟构造方法:
public void test6(@Mocked Model app){
new Expectations() {
{
new Model();
result = app;
app.getAge();
result = 111;
app.getPName();
result = "lisi";
}
};
System.out.println(new Model().getAge());
System.out.println(new Model().getPName());
}
虚拟私有方法:
new Expectations(app) {
{
Deencapsulation.invoke(app, "getName");
result = "lisi";
}
assertThat("lisi", equalTo(app.getPName()));
虚拟静态方法:
new Expectations(Model.class) {
{
Deencapsulation.invoke(Model.class, "getName");
result = "lisi";
}
};
assertThat("lisi", equalTo(Model.getPName()));
用Delegate类返回值
new Expectations(app) {
{
app.getAge();
result = new Delegate(){
int aaa(){
return 1;
}
};
}
};
注:里面的实现方法名称可以任意,但只能存在一个方法,且不能为私有
一些关键字
对模拟调用次数限制:times = ? 次数
minTimes = ? 最小
maxTime = ? 最大
minTime = ? ;maxTime = ? 在之间
anyString 等 any…系列字段:表示任何这种类型