前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >不会测试的程序员不是好程序员(一文让你掌握JMockit的使用)

不会测试的程序员不是好程序员(一文让你掌握JMockit的使用)

作者头像
IT学习日记
发布2022-09-13 16:03:34
1.2K0
发布2022-09-13 16:03:34
举报
文章被收录于专栏:IT知识进阶学习IT知识进阶学习

一: 前言

  俗话说: “不会测试的开发不是好开发,不会Mock的测试不是好测试”。测试在开发中时必不可少的一环,正规的开发流程中,只有自测通过了,才会将功能提交到真正的测试人员中进行其他测试。对自己负责就是对他人负责,所以,学会测试是每个开发人员必备的一项技术。

二: 常见的测试种类

  • 1、单元测试: 对功能的最小单位(方法)进行测试(包括黑盒、白盒、灰盒测试)。
  • 2、白盒测试: 不但关注测试的输入数据和输出结果,还关注程序的执行逻辑。
  • 3、黑盒测试: 对程序的执行逻辑不关注,只关注测试的输入和输出。
  • 4、灰盒测试: 介于白盒测试与黑盒测试之间,注重程序运行的逻辑流程
  • 5、压力测试: 测试同一时间,并发情况下程序的执行情况。
  • 6、.....

三: JMockit的定义

  Mock: 英文意思有模仿、嘲笑的含义。

  JMockit: 是一种Java类/接口/对象的Mock工具,是现在JAVA程序单元测试比较常见的方式。

  Mock工具的种类: 常见的EasyMock、Mockito等。

  为什么选择JMockit: 首先、它是完全以面向对象的方式提供API,其次,它是其他Mock工具的功能的集大成者,学习知识就要学习功能性比较完成的,选择JMockit时正确的选择,具体功能对比如下:

在这里插入图片描述
在这里插入图片描述

四: JMockit常用知识讲解

  一: JMockit常用的知识点

  (一): JMockit主要是由:测试属性或测试参数,测试方法组成。其中测试方法又包括; 录制代码块,重放测试逻辑,验证代码块三部分。

  (二)测试属性:既测试类中的一个属性,它作用于测试类的所有方法,可以使用JMockit中的@Mocked, @Tested, @Injectable,@Capturing进行修饰。添加上这些注解表示这个属性它的实例化,属性赋值,方法调用的返回值全部由JMockit来接管,也就是意味着可以通过录制行为来自定义测试属性的具体实现,具体图如下:

在这里插入图片描述
在这里插入图片描述

  (三) 测试参数(其实就是方法的参数,跟测试属性的区别就是作用域不一样):

  在测试类中参数加了JMockit的注解API(@Mocked, @Tested, @Injectable,@Capturing),原本的测试方法是不可以添加参数的,但是如果参数中添加了JMockit的注解的话,就可以在测试方法中添加参数,它表示的意思是仅作用于当前的测试方法,具体图如下:

在这里插入图片描述
在这里插入图片描述

  (四): 测试方法

  由录制代码块,重放测试逻辑,验证代码块三部分组成,既Record-Replay-Verification。

  1、Record(录制): 即先录制某类/对象的某个方法调用,在当输入什么时,返回什么。

在这里插入图片描述
在这里插入图片描述

2、Replay(重放): 重放测试逻辑,实际上就是调用上面录制的方法

在这里插入图片描述
在这里插入图片描述

3、重放后的验证。比如验证某个方法有没有被调用,调用多少次。

在这里插入图片描述
在这里插入图片描述

  二: JMockit常用API注解及区别

  (一) @Mocked:修饰类/接口时,就是告诉JMockit,生成一个被修饰类/接口的Mock对象,这个对象中方法(包含静态方法)返回默认值。即如果返回类型为原始类型(short,int,float,double,long)就返回0,如果返回类型为String就返回null,如果返回类型是其它引用类型,则返回这个引用类型的Mocked对象(就类型与生成一个假对象,这个对象里面方法逻辑不存在,可以通过录制行为去控制)。

  (二) Mocked的使用场景: 测试程序依赖某个接口时,用@Mocked非常适合了。只需要@Mocked一个注解,JMockit就能帮我们生成这个接口的实例。如: 分布式系统中存在一个服务调用另一个服务的接口时,可以直接通过Mock生成实例,不需要启动微服务测试。

在这里插入图片描述
在这里插入图片描述

  (三) @Injectable注解:作用是告诉JMockit生成一个Mocked对象,但@Injectable只是针对其修饰的实例,而@Mocked是针对其修饰类的所有实例,@Injectable对类的静态方法,构造函数没有影响。因为它只影响某一个实例。

在这里插入图片描述
在这里插入图片描述

  (四) @Tested: 作用是表示被测试对象。如果该对象没有赋值,JMockit会去实例化它,若@Tested的构造函数有参数,则JMockit通过在测试属性&测试参数中查找@Injectable修饰的Mocked对象注入@Tested对象的构造函数来实例化,

  不然,则用无参构造函数来实例化。除了构造函数的注入,JMockit还会通过属性查找的方式,把@Injectable对象注入到@Tested对象中。注入的匹配规则:先类型,再名称(构造函数参数名,类的属性名)。若找到多个可以注入的@Injectable,则选择最优先定义的@Injectable对象。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  (五)@Tested & @Injectable 的使用场景:需要手工管理被测试类的依赖时,就需要用到@Tested & @Injectable。两者搭配起来用,JMockit就能帮我们轻松搞定被测试类及其依赖注入细节。

五: JMockit实战

  (一) 引入依赖坐标(JUnit4.x及以下用户特别注意事项,如果你是通过mvn test来运行你的测试程序 , 请确保JMockit的依赖定义出现在JUnit的依赖之前,否则会报错):

代码语言:javascript
复制
 <!-- https://mvnrepository.com/artifact/org.jmockit/jmockit -->
        <dependency>
            <groupId>org.jmockit</groupId>
            <artifactId>jmockit</artifactId>
            <version>${jmockit.version}</version>
        </dependency>

  (二) 构建需要测试的测试类

代码语言:javascript
复制
// 测试数据类,常规来说我们如果想调用这些方法则需要通过Mybatis或者其数据层操作组件才能够调用
// 但测试通过JMockit可以Mock一个Dao对象,来完成我们的需求
public interface UserDao {

    Integer deleteUser(Integer id);

    User getUserById(Integer id);

    List<User> getUserList();

    Integer insertUser(User user);

    Integer updateUser(User user);

    Integer test(Integer test);
}

  (三) 书写测试类:

代码语言:javascript
复制
public class JmockitDemo {
    // 这是一个测试属性,使用Mock标识,表示UserDao的它的实例化,属性赋值,
    // 方法调用的返回值全部由JMockit来接管,可以通过录制行为来控制属性中的行为
    @Mocked
    UserDao userDao;

    @Test
    public void testSeletById(){
        User users = new User(19);
        /**
         * 步骤:
         *  1、录制行为-Record,设置预期值
         *  2、重放行为-replay,查看预期值
         *  3、校验行为-verification,用于查看程序执行是否跟自己设想一直
         *  注意事项:
         *  你录制多少个行为,就需要在下面播放多少个行为,否则会报错: Missing 1 invocation to(缺少预期行为的调用)
         */
        // 可以录制多个行为
        new Expectations(){
            {
                // 加上删除用户时传入12,我预期返回的结果是result后的值
                userDao.deleteUser(12);
                // result表示执行上面的行为后,预期返回的结果
                result = 123;
                userDao.getUserById(13);
                // result表示执行上面的行为后,预期返回的结果
                result = new User(12);
                userDao.getUserList();
                List<User> a= new ArrayList<>();
                User user = new User(123);
                User user1 = new User(124);
                a.add(user);
                a.add(user1);
                // result表示执行上面的行为后,预期返回的结果
                result = a;
            }
        };
        //..Assert.assertTrue(123 == userDao.deleteUser(12));
        // 重放
        Integer integer = userDao.deleteUser(12);
        System.out.println(integer);
        User userById = userDao.getUserById(13);
        System.out.println(userById.getId());
        //Assert.assertTrue(123 == userDao.getUserById(13).getId());
    }
}

  (四) 执行结果:

在这里插入图片描述
在这里插入图片描述

写在最后

很多时候,找到符合自己的工具比盲目地开始更加重要,开源是现在也是未来的主流,希望能够有更多有志之士加入开源,建设更好的开源生态。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022/06/18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一: 前言
  • 二: 常见的测试种类
  • 三: JMockit的定义
  • 四: JMockit常用知识讲解
  • 五: JMockit实战
  • 写在最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档