1 pom配置
testng + jmockit,使用junit也可以
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.41</version>
<scope>test</scope>
</dependency>
</dependencies>
2 程序结构
三步走:
- 录制,mock方法并返回指定结果
- 回放,调用mock的方法
- 验证,检查mock方法使用情况
public class App {
public String say(String name) {
return "Hello " + name;
}
}
---------------------------------------------
public class AppTest {
@Mocked App app;
@Test
public void testSay() {
//录制
new Expectations() {{
app.say(anyString);
result = "Hello World";
}};
//回放
System.out.println(app.say("Jack"));
//验证
new Verifications() {{
app.say(anyString);
times = 1;
}};
}
}
3 @Mocked/@Tested/@Injectable
- @Mocked
- mock整个对象,自动实例化对象,对象的方法(包括类方法)均返回默认值(int,short,double等返回0,String返回null)
- @Injectable
- 相较于@Mocked,只影响当前实例,新new的实例不在mock范围内
- 因为受限于当前实例,所以类的静态方法也不受影响
- @Tested
- 一般与@Injectable配合使用,@Tested标识被测对象,并自动实例化;如果其构造函数有参数,会自动将@Injectable对象注入
public class App {
public String say() {
return "Hello World";
}
public static String staticSay() {
return "Still hello world";
}
}
public class AppTest {
@Mocked App app;
@Test
public void testSay() {
System.out.println(app.say());
System.out.println(new App().say());
System.out.println(App.staticSay());
}
}
-----------
null
null
null
public class AppTest {
@Injectable App app;
@Test
public void testSay() {
System.out.println(app.say());
System.out.println(new App().say());
System.out.println(App.staticSay());
}
}
-----------
null
Hello World
Still hello world
4 Expectations
new Expectations() {
//使用匿名内部类的形式实例化
{
//通过构造代码块完成初始化
//录制方法
//指定返回结果result
}
}
在一个Expectations中可以同时录制多个行为,也可以分开多个Expectations录制
2种使用方式
- 引用@Mocked/@Injectable对象,实现整体模拟
- 在Expectations中传入类作为参数,实现类的局部模拟
通过下面的例子观察二者的区别:前者影响到录制外的方法;后者保留录制外的方法,只影响录制方法本身
public class AppTest {
@Mocked
App app;
@Test
public void testSay() {
new Expectations() {{
App.staticSay();
result = "Goodbye";
}};
System.out.println(app.say());
System.out.println(App.staticSay());
}
}
-----------
null
Goodbye
public class AppTest {
@Test
public void testSay() {
App app = new App();
new Expectations(App.class) {{
App.staticSay();
result = "Goodbye";
}};
System.out.println(app.say());
System.out.println(App.staticSay());
}
}
-----------
Hello World
Goodbye
5 MockUp & @Mock
有点像@override方式,将mock方法覆写一遍
public class AppTest {
@Test
public void testSay() {
new MockUp<App>(App.class) {
@Mock
String say() {
return "byebye";
}
@Mock
String staticSay() {
return "Also byebye";
}
};
System.out.println(new App().say());
System.out.println(App.staticSay());
}
}
-----------
byebye
Also byebye
它的强大之处在于,可以定制方法体,按照自己的想法和逻辑返回期望的结果
6 Verifications
同Expectations一样,使用匿名内部类实例化
主要验证mock方法是否被调用,以及调用了多少次
public class AppTest {
@Mocked
App app;
@Test
public void testSay() {
new Expectations() {{
app.say();
result = "byebye";
App.staticSay();
result = "Also byebye";
}};
System.out.println(app.say());
System.out.println(App.staticSay());
new Verifications() {{
app.say();
times = 1;
App.staticSay();
times = 2;
}};
}
}
------------
byebye
Also byebye
Missing 1 invocation to:
org.lab.App#staticSay()
网友评论