Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

androidjp/springboot-jmockit-junit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

6 Commits

Repository files navigation

springboot-jmockit-junit

一句话:JMockit 很强大,但是,入门门槛相比PowerMock会高一点。

  • JMockit必须在JDK1.7或以上跑。
  • JMockit必须使用JUnit/TestNG
  • 细节:Maven pom.xml中写依赖时,要先写JMockit,后写JUnit,否则,需要每一个测试类都加上注解@RunWith(JMockit.class)
  • 细节:配合TestNG使用,不是加@RunWith()注解,而是extends AbstractTestNGSpringContextTests

注解分析

  • @Tested
    • 自动创建被测对象。(调用该类的无参构造器)
    • @Tested(fullyInitialized = true)表示对当前被测对象进行递归初始化,他内部的所有依赖都会被正常初始化,不存在mock。
    • 注意:@Tested修饰的对象,已经要是实现类,不要是接口类型,否则报错。
  • @Injectable
    • 仅对当前实例的所有方法进行mock
  • @Mocked
    • 今后的所有实例进行mock
  • @Capturing
    • 对本类方法全部mock
    • 对本接口的所有子类/实现类mock

注意:无论是@Injectabe,@Mocked,@Capturing哪种Mock对象,都是对类的方法全部mock了

用法示例:

  1. Mock Service 中依赖的 DAO

    public class DiyServiceImplTest {
     /// 被测 对象
     @Tested
     private DiyServiceImpl diyService;
     @Test
     public void testBuildCompatibleComputer(@Injectable ComputerDAO pcDaoImpl) throws Exception {
     // step1: mock 对象指定方法的模拟返回值
     new Expectations() {
     {
     pcDaoImpl.getComputersByCost(anyDouble, anyDouble);
     result = new ArrayList<Computer>();
     }
     };
     // step2: 进行测试
     Computer computer = diyService.buildCompatibleComputer(5000, "game");
     Assert.assertTrue(computer == null);
     // step3:验证被mock的方法执行次数
     new Verifications() {
     {
     pcDaoImpl.getComputersByCost(4500,5500);
     times = 1;
     }
     };
     }
    }
  2. Mock 一个对象中的部分方法

    详细看:ExpectationsSample.java

    其实就是对一个带有@Tested注解的对象,在方法中加上对其部分方法的expect设置

    @Tested
    private Person person;/// or Person person = new Person();
    .......
    @Test
    public void test01(){
     new Expectations(person){///针对这个实例
     person.run(1);
     result = "success";
     }
     ......
    }
  3. Mock 静态属性和private属性

    详细看:CakeFactoryTest.java

    用到的是Deencapsulation

    new Expectataions(类名.class/类实例){
    {
     { 
     Deencapsulation.setField(类实例, "CAKE_NAME", "被Mock的蛋糕仔"); 
     }
    }
  4. Mock 静态方法

    详细看:PcFixServiceImplTest.itShouldBeActiveIfInvoiceDeadlineIsOk()

    直接把静态方法所在类名扔进Expectations参数中,对你想mock的静态方法进行mock即可。

  5. Mock private方法

    详细看:CakeFactoryTest.testMockPrivateMethodAndField()

    还是用到的是Deencapsulation

    new Expectataions(类名.class/类实例){
    {
     { 
     Deencapsulation.invoke(类实例, "method_name", ...args); 
     result = xxx;
     }
    }

    注意:由于最高版本 1.39 不支持 private 方法的mock,所以,本项目采用的是 1.19版本(最多人用的版本)。

  6. Mock final 属性

    由例子CakeFactoryTest.testMockFinalField()可以看出,final属性无法被mock。

  7. Mock final 方法

    详细看:CakeFactoryTest.testMockFinalMethod()

    mock public final 的 方法,可mock 普通的 public的方法一样:

    new Expectations(对象) {
     {
     对象.finalMethod();
     result = "xxx";
     }
    };

    mock private final 方法,其实和mock 普通的 private方法一样,还是用到的是Deencapsulation:

    new Expectataions(类名.class/类实例){
    {
     { 
     Deencapsulation.invoke(类实例, "private_final_method_name", ...args); 
     result = xxx;
     }
    }

MockUp+@Mock VS Expectations

如果不想遵循:record -> replay -> verify 这样的 mock 模式,那么,我们还可以选择使用MockUp+@Mock.

  • 好处:
    1. 全局mock好了方法要干嘛,不需要每个方法再写 new Expectations(){}
  • 特点:
    1. 对这个类的今后所有实例都进行mock
  • 缺点:
    1. 如果只想对某一对象进行mock,就不行了,只有Expectations能做到
    2. 相应的,你没写Expectations,那你就不能写Verifications,就不能验证方法执行次数了。

参考文章

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

AltStyle によって変換されたページ (->オリジナル) /