当前位置: 首页 > 工具软件 > JMockit > 使用案例 >

JMockit简单使用

濮书
2023-12-01

JMockit简单使用

1. 参考文档

JMockit中文网

2. 是什么?

2.1. 简介

JMockit是一款Java类/接口/对象的Mock工具,目前广泛应用于Java应用程序的单元测试

一句话说明功能:你需要什么就可以mock什么。(比如本地没有Redis但是开发时又需要用到,那么就可以mock一个Redis的功能来隔离对Redis的依赖)

2.2. 基本流程

record(录制)---- replay(回放) ---- verify(验证)

1、record : 设置将要被调用的方法和返回值。

  • Expections中的方法至少被调用一次,否则会出现missing invocation错误。调用次数和调用顺序不限。
  • StrictExpectations中方法调用的次数和顺序都必须严格执行。如果出现了在StrictExpectations中没有声明的方法,会出现unexpected invocation错误。

2、replay:调用录制的方法,被录制的方法调用会被JMockit拦截并重定向到record阶段设定的行为。

3、verify:基于行为的验证,测试是否正确调用了依赖类,包括:调用了哪些方法;通过怎样的参数;调用了多少次;调用的相对顺序等。可以使用times,minTimes,maxTimes来验证。

3. 怎么用?

3.1. 引入依赖

<!-- 先声明jmockit的依赖 -->
<dependency>
    <groupId>org.jmockit</groupId>
    <artifactId>jmockit</artifactId>
    <version>1.36</version>
    <scope>test</scope>
</dependency>

<!-- 如果没有引入junit依赖就加上下面依赖 -->
<!-- 再声明junit的依赖 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

3.2. 使用

3.2.1. 简单案例

将 jmockitInt() 方法的返回值 mock 成 100

public class JMockitDemo1001 {
    // 获取int值
    public int jmockitInt(){
        return 10;
    }
}

// JMockit测试
@Test
public void jmockitIntTest(){
    JMockitDemo1001 jMockitDemo1001 = new JMockitDemo1001();
    // mock前返回值为 10
    Assert.assertEquals(jMockitDemo1001.jmockitInt(), 10);
    // 1、录制
    new Expectations(JMockitDemo1001.class) {
        {
            // 将该方法返回值 mock 为 100
            jMockitDemo1001.jmockitInt();
            result = 100;
        }
    };
    // 2、回放
    Assert.assertEquals(jMockitDemo1001.jmockitInt(), 100);
    // 3、验证
    new Verifications(){
        {
            jMockitDemo1001.jmockitInt();
            times  = 1;
        }
    };
}

3.2.2. @Mocked

  • @Mocked修饰的类/接口,是告诉JMockit,帮我生成一个Mocked对象,这个对象方法(包含静态方法)返回默认值
  • 如果返回类型为原始类型(short,int,float,double,long)就返回0,如果返回类型为String就返回null,如果返回类型是其它引用类型,则返回这个引用类型的Mocked对象
public class JMockitMocked {
    public static String strDataStatic = "strDataStatic";
    public static int intDataStatic = 10;
    public String strData = "strData";
    public int intData = 1;

    public static String getStrDataStatic(){
        return strDataStatic;
    }

    public static int getIntDataStatic(){
        return intDataStatic;
    }

    public String getStrData(){
        return strData;
    }

    public int getIntData(){
        return intData;
    }
}


// mocked测试
public class JMockitMockedTest {
    @Mocked
    JMockitMocked jMockitMocked;

    @Test
    public void test1001(){
        System.out.println(JMockitMocked.strDataStatic);  // strDataStatic
        System.out.println(JMockitMocked.intDataStatic);  // 10
        System.out.println(jMockitMocked.strData);  // null
        System.out.println(jMockitMocked.intData);  // 0

        System.out.println(JMockitMocked.getStrDataStatic());  // null
        System.out.println(JMockitMocked.getIntDataStatic());  // 0
        System.out.println(jMockitMocked.getStrData());  // null
        System.out.println(jMockitMocked.getIntData());  // 0
    }
}

3.2.3. @Injectable

@Injectable 也是告诉 JMockit生成一个Mocked对象,但@Injectable只是针对其修饰的实例,而@Mocked是针对其修饰类的所有实例

  • @Injectable对类的静态方法,构造函数不进行mock
public class JMockitMocked {
    public static String strDataStatic = "strDataStatic";
    public static int intDataStatic = 10;
    public String strData = "strData";
    public int intData = 1;

    public static String getStrDataStatic(){
        return strDataStatic;
    }

    public static int getIntDataStatic(){
        return intDataStatic;
    }

    public String getStrData(){
        return strData;
    }

    public int getIntData(){
        return intData;
    }
}


// mock测试
public class JMockitInjectableAndTestedTest {
    // @Mocked
    @Test
    public void test1001(@Mocked JMockitInjectableAndTested jMockitInjectableAndTested){
        System.out.println(JMockitInjectableAndTested.getStrDataStatic());  // null
        System.out.println(JMockitInjectableAndTested.getIntDataStatic());  // 0
        System.out.println(jMockitInjectableAndTested.getStrData());  // null
        System.out.println(jMockitInjectableAndTested.getIntData());  // 0
    }

    // @Injectable
    @Test
    public void test1002(@Injectable JMockitInjectableAndTested jMockitInjectableAndTested){
        System.out.println(JMockitInjectableAndTested.getStrDataStatic());  // strDataStatic
        System.out.println(JMockitInjectableAndTested.getIntDataStatic());  // 10
        System.out.println(jMockitInjectableAndTested.getStrData());  // null
        System.out.println(jMockitInjectableAndTested.getIntData());  // 0
    }
}

3.2.4. MockUp & @Mock

MockUp & @Mock 的联合使用可以只 mock 对象的部分方法(当需要 mock 整个对象就可以考虑使用 @Mocked 或 @Injectable)

public class JMockitMockUpAndMock {
    public int getIntData1001(int num){
        return num;
    }

    public int getIntData1002(int num){
        return num;
    }
}

// mock测试
public class JMockitMockUpAndMockTest {
    @Test
    public void test1001(){
        // 只需要把JMockitMockUpAndMock类传入MockUp类的构造函数
        new MockUp<JMockitMockUpAndMock>(JMockitMockUpAndMock.class) {
            // 想Mock哪个方法,就给哪个方法加上@Mock, 没有@Mock的方法,不受影响
            @Mock
            public int getIntData1001(int num) {
                return 10 * num;
            }
        };
        JMockitMockUpAndMock jMockitMockUpAndMock = new JMockitMockUpAndMock();
        System.out.println(jMockitMockUpAndMock.getIntData1001(2));  // 20
        System.out.println(jMockitMockUpAndMock.getIntData1002(2));  // 2
    }
}
 类似资料: