美文网首页
Jmockit(二): 场景应用

Jmockit(二): 场景应用

作者: halfempty | 来源:发表于2018-11-13 22:15 被阅读0次

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
    }
}

相关文章

网友评论

      本文标题:Jmockit(二): 场景应用

      本文链接:https://www.haomeiwen.com/subject/bberfqtx.html