JMockit单元测试用法

2018-06-02  本文已影响525人  visionarywind

基础概念

Record: 即先录制某类/对象的某个方法调用,在当输入什么时,返回什么
Replay: 即重放测试逻辑
Verification: 重放后的验证

API用法

@Mocked

加上了JMockit的API @Mocked, JMockit会实例化这个对象
Mocked可以用来修饰类、接口和抽象类,返回默认值(如果是原始类型,返回原始值的默认值,如果为其他对象,则返回一个同样被Mocked的对象)
Mocked十分粗暴,会mock掉整个的实现

@Injectable

@Injectable功能跟@Mocked相似,区别是@Injectable只针对修饰的实例,对mock类的静态方法、构造函数没有影响

@Tested

@Tested表示被测试对象。如果该对象没有赋值,JMockit会去实例化它,若@Tested的构造函数有参数,则JMockit通过在测试属性&测试参数中查找@Injectable修饰的Mocked对象注入@Tested对象的构造函数来实例化,
不然,则用无参构造函数来实例化。除了构造函数的注入,JMockit还会通过属性查找的方式,把@Injectable对象注入到@Tested对象中。
注入的匹配规则:先类型,再名称(构造函数参数名,类的属性名)。若找到多个可以注入的@Injectable,则选择最优先定义的@Injectable对象

@Capturing

@Capturing主要用于子类/实现类的Mock,比如java动态代理生成的类,这些类没有名字,无法进行正常的mock
当只知道父类或接口时,但需要控制其子类的行为时,子类可能有多个实现(可能有人工写的,也可能是AOP代理自动生成时),需要使用@Capturing

Expectations

Record对象的核心方法,最核心和重要的注解了,可以和引用外部类的Mock对象(@Injectabe,@Mocked,@Capturing)来录制,也可以通过构建函数注入类/对象来录制
限制:不能mock对象的native方法和private方法

MockUp & Mock

MockUp & @Mock提供更改代码行为的Mock方式,最强大mock实现,主要有以下限制:

Verifications

Verifications是用于做验证,过程式编程的福音
验证Mock对象(即@Moked/@Injectable@Capturing修饰的或传入Expectation构造函数的对象)有没有调用过某方法,调用了多少次
主要用于一些没有返回值的代码验证

实例

//一个普通类 
public class AnOrdinaryClass {
    // 静态方法
    public static int staticMethod() {
        return 1;
    }
    // 普通方法
    public int ordinaryMethod() {
        return 2;
    }
    // final方法
    public final int finalMethod() {
        return 3;
    }
    // native方法,返回4
    public native int navtiveMethod();
    // private方法
    private int privateMethod() {
        return 5;
    }
    // 调用private方法
    public int callPrivateMethod() {
        return privateMethod();
    }
}
public class Sample {
    private SampleDepend sampleDepend;
    private SampleInterface sampleInterface = new SampleInterface() {
        @Override
        public int call() {
            return 1;
        }
    };

    public Sample() {
    }

    public int getSampleDependVal() {
        return sampleDepend.getVal();
    }

    private static int staticGetOne() { return 1; }
    public static int staticGetPrivateOne() { return staticGetOne(); }

    private int getOne() { return 1; }
    public int getPrivateOne() { return getOne(); }

    public void execute() {
        sampleDepend.getVal();
        doExecute(); }

    private void doExecute() {}

    public int interfaceCall() {
        return sampleInterface.call();
    }

    public interface SampleInterface {
        int call();
    }
}
public class SampleDepend {
    private int val;
    public int getVal() { return val; }
    public void setVal(int val) { this.val = val; }
}

@RunWith(JMockit.class)
public class SampleTest {
    @Tested
    private Sample sample;

    @Test
    public void testStaticGetPrivateOne() {
        new Expectations(sample) {
            {
                Deencapsulation.invoke(sample, "staticGetOne");
                result = 2;
            }
        };

        Assert.assertTrue(sample.staticGetPrivateOne() == 2);
    }

    @Test
    public void testGetPrivateOne() {
        new Expectations(sample) {
            {
                Deencapsulation.invoke(sample, "getOne");
                result = 2;
            }
        };

        Assert.assertTrue(sample.getPrivateOne() == 2);
    }

    @Test
    public void testGetSampleDependVal(@Injectable SampleDepend sampleDepend) {
        new Expectations(sampleDepend) {
            {
                sampleDepend.getVal();
                result = 2;
            }
        };
        Assert.assertTrue(sample.getSampleDependVal() == 2);
        Assert.assertTrue(sample.getSampleDependVal() == 0);
    }

    @Test
    public void testExecute(@Injectable SampleDepend sampleDepend) {
        sample.execute();
        new Verifications() {
            {
                sampleDepend.getVal();
                times = 1;
                Deencapsulation.invoke(sample, "doExecute");
                times = 1;
            }
        };
    }

    @Test
    public void testInterfaceCallWithInjectable(@Injectable Sample.SampleInterface sampleInterface) {
        Deencapsulation.setField(sample, "sampleInterface", sampleInterface);
        new Expectations() {
            {
                sampleInterface.call();
                result = 2;
            }
        };
        Assert.assertTrue(sample.interfaceCall() == 2);
    }

    @Test
    public void testInterfaceCallWithCapturing(@Capturing Sample.SampleInterface sampleInterface) {
        new Expectations() {
            {
                sampleInterface.call();
                result = 2;
            }
        };
        Assert.assertTrue(sample.interfaceCall() == 2);
    }
}

一个完整的PDF

上一篇 下一篇

猜你喜欢

热点阅读