51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 471|回复: 1
打印 上一主题 下一主题

[原创] 浅谈Mock技术在JAVA微服务单元测试中的应用

[复制链接]
  • TA的每日心情
    无聊
    3 天前
  • 签到天数: 1050 天

    连续签到: 1 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2023-3-21 09:52:33 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
    摘要:在系统开发的过程中,单元测试是其中的一个重要环节。在Java微服务项目中,Spring框架本身就为我们提供了一套单元测试的框架SpringBootTest。如果我们在学校完成课堂作业或出于兴趣爱好自学,是可以使用Spring自带的单元测试框架进行单测的。
      工作中,这种通过SpringBootTest进行单元测试的方式则不推荐使用。其缺点在于,每次执行测试方法都必须启动Spring容器。当项目规模较大、配置较为复杂时,即使只对一个方法进行测试,也需要消耗大量时间启动Spring容器。当我们期望对DAO层方法进行测试时,该方法还有其他缺点:① 如果忘记加进行事务控制的注解,将可能导致数据库产生“脏数据”或数据缺失。② 当查询语句涉及大量连表查询时,查询效率可能十分低下,执行速度缓慢。③ 由于必须根据数据库中已有的数据来编写测试条件,每次必须先去数据库确保哪些数据存在、哪些数据不存在,再编写对应返回正确值、返回错误值的单元测试,开发效率低下。
      针对上述问题,可能有人会想到使用H2内存数据库的方式加以解决。不过,这依然无法有效地解决执行单元测试需要启动Spring容器的问题和上述问题③,假设我们期望执行用户查询返回一条姓名为xxx、年龄为xxx的记录,我们依然需要去sql文件中编写这一条记录的插入语句,并且也需要大量的配置。如果有很多条需要模拟的数据记录,就需要创建很多表、编写很多sql语句,开发效率依然大打折扣。
      此时,有一种很好的解决方案,既不需要和真实的数据库交互,也不需要启动Spring容器,同时又不需要编写大量的测试数据源,它就是Mock。使用Mock进行单元测试,我们可以直接模拟出结果,而不需要准备数据源。本文以简单的用户功能为例,说明如何使用Mock来进行DAO层的单元测试。
      1、使用Spring原生的方法进行测试。我们假设ID=1的用户记录是存在的,那么查询结果必定不为NULL。假设ID=2的用户记录是不存在的,那么查询结果必定为NULL。该方式需要启动Spring容器,并与数据库发生真实交互。

      2、使用Mock进行测试。该方式不需要启动Spring容器,也不与数据库发生真实交互。
      2.1、首先,引入Mock所需的pom依赖

      2.2、使用运行Mock框架的注解@RunWith(MockitoJUnitRunner.class)
      替换Spring原生单元测试的注解@SpringBootTest

      2.3、给Service层对象加上@InjectMocks注解,给Dao层对象加上@Mock注解。其中,@InjectMocks注解对象的方法会进行真实调用(会真实调用已编写的代码并返回执行结果),而@Mock注解对象的方法则是进行模拟调用(不会真实调用已编写的代码并返回我们设置的预期执行结果)。

      2.4、具体的单元测试方法中,通过Mockito.when(模拟方法).thenReturn(预期返回值)的方式,进行单元测试。

      上述方法中,“Mockito.when(userDAO.findUserById(1L)).thenReturn(new User())”的含义是,当userDAO调用findUserById进行查询且参数为1L时,会返回一个new的User对象。
      同理,“Mockito.when(userDAO.findUserById(2L)).thenReturn(null)”的含义是,当userDAO调用findUserById进行查询且参数为2L时,会返回一个空对象。
      当测试涉及的数据记录较多,逻辑较复杂时,使用Mock模拟DAO层的测试所提升单元测试的执行效率将更加明显。
      此外,当我们本地在开发调试时,如果数据库的测试数据发生了改变,那么我们单元测试的结果也会受到影响。例如,数据库中原本存在ID=1的记录,如果不小心删掉了,那么我们单测中Assert.assertNotNull的方法就会报错。而如果使用Mock的形式,无论数据库中是否存在该记录,我们执行DAO层方法的返回值都只依赖于我们在thenReturn方法中设置的值。
      总结一下使用Mock模拟DAO层方法测试的优点:
      1、不需要启动Spring容器
      2、不需要与数据库发生真实交互,不会导致脏数据产生、不会受到数据库真实数据的影响、不需要为了单元测试额外添加/修改/删除数据
      3、启动速度快、执行速度快、开发简单且效率高

    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    该用户从未签到

    2#
    发表于 2023-3-28 16:59:57 | 只看该作者
    Mock的这种使用方式需要修改开发代码,只适合开发使用。测试使用时,mock主要用于更外层的接口调用返回值的处理。从而达到当前测试不依赖于外部接口或数据的目的。
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-24 14:05 , Processed in 0.065602 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表