前言
一个服务经常会关联多个其他服务来一起完成一项工作,而我们在写测试用例的时候是聚焦在某个小单元的业务上,所以外部的一些服务我们可以给他屏蔽掉。这边的屏蔽不是完全的不去管它,而是希望外部服务虽然没有真实触发,但是它可以模拟返回我们要的结果。Mock
就是用来帮助我们完成这个过程的。
1. @Mocked
普通对象的 Mock 可以借助 @Mocked 完成。主要由 录制、回放、验证 三步骤完成,是对某个类的所有实例的所有方法进行完整的模拟方式。
针对类及所有实例的的整体模拟,未写录制的方法默认返回0 或 null。 由于作用范围比较广,建议在某个具体的单测方法参数里面定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
public class App {
public String say() { return "Hello World"; }
public String say2(){ return "Hello World 2"; }
public static String staticSay() { return "Still hello world"; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
public class AppTest {
@Test public void testSay(@Mocked App app) {
new Expectations() {{ app.say(); result = "say"; }};
System.out.println(app.say()); System.out.println(new App().say()); System.out.println(App.staticSay());
new Verifications() {{ app.say(); times = 2;
App.staticSay(); times = 1; }};
} }
|
2. @Injectable
@Injectable 和 @Mocked 的方式很像,区别是 @Injectable 仅仅对当前实例进行模拟,而 @Mocked 是对所有实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
public class AppTest001 {
@Injectable App app;
@Test public void testSay() {
new Expectations() {{ app.say(); result = "say"; }};
System.out.println(app.say()); System.out.println(app.say2());
final App appNew = new App(); System.out.println(appNew.say()); System.out.println(App.staticSay());
new Verifications() { { app.say(); times = 1; } { appNew.say(); times = 1; } { App.staticSay(); times = 1; } };
} }
|
3. Expectations
录制,带参数表示局部模拟【针对所有实例的局部模拟,具体到某个方法的模拟,其它方法不模拟】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public class AppTest002 {
@Test public void testSay() {
final App app = new App();
new Expectations(App.class) {{ app.say(); result = "say"; }};
System.out.println(app.say()); System.out.println(app.say2()); System.out.println(new App().say()); System.out.println(App.staticSay());
} }
|
4. MockUp
局部模拟,不是简单的返回,可重写原有方法的逻辑,比较灵活,推荐使用。(静态方法也能用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public class AppTest003 {
@Test public void testSay() { new MockUp<App>(App.class){ @Mock String say(){ return "say"; } }; System.out.println(new App().say()); System.out.println(new App().say2()); System.out.println(App.staticSay());
} }
|
5. Capturing
mocked 的增强版本,可以 mock 接口和静态类,如果 Capturing
某个接口,那么该接口下的所有方法都会自动被 mock
1 2 3 4 5 6 7 8 9 10
| @Test public void sonarCallBak(@Capturing EsClient esClient) throws UnsupportedEncodingException { new Expectations() { { esClient.createDoc(withInstanceOf(SimpleDocVo.class), withInstanceOf(PipelineJobSonar.class)); result = "{}"; times = 1; } }; ...
|