我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SpringBoot单元测试框架Mockito介绍及使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SpringBoot单元测试框架Mockito介绍及使用

Mockito 是一种 Java mock 框架,他主要是用来做 mock 测试的,他可以模拟任何 Spring 管理的 bean、模拟方法的返回值、模拟抛出异常...等,在了解 Mockito 的具体用法之前,得先了解什麽是 mock 测试

1. 什么是mock测试

mock 测试就是在测试过程中,创建一个假的对象,避免你为了测试一个方法,却要自行构建整个 bean 的依赖链

像是以下这张图,类 A 需要调用类 B 和类 C,而类 B 和类 C 又需要调用其他类如 D、E、F 等,假设类 D 是一个外部服务,那就会很难测,因为你的返回结果会直接的受外部服务影响,导致你的单元测试可能今天会过、但明天就过不了了

而当我们引入 mock 测试时,就可以创建一个假的对象,替换掉真实的 bean B 和 C,这样在调用B、C的方法时,实际上就会去调用这个假的 mock 对象的方法,而我们就可以自己设定这个 mock 对象的参数和期望结果,让我们可以专注在测试当前的类 A,而不会受到其他的外部服务影响,这样测试效率就能提高很多

2. Mockito简介

说完了 mock 测试的概念,接下来我们进入到今天的主题,Mockito

Mockito 是一种 Java mock 框架,他主要就是用来做 mock 测试的,他可以模拟任何 Spring 管理的 bean、模拟方法的返回值、模拟抛出异常...等,他同时也会记录调用这些模拟方法的参数、调用顺序,从而可以校验出这个 mock 对象是否有被正确的顺序调用,以及按照期望的参数被调用

像是 Mockito 可以在单元测试中模拟一个 service 返回的数据,而不会真正去调用该 service,这就是上面提到的 mock 测试精神,也就是通过模拟一个假的 service 对象,来快速的测试当前我想要测试的类

目前在 Java 中主流的 mock 测试工具有 Mockito、JMock、EasyMock..等,而 SpringBoot 目前内建的是 Mockito 框架

题外话说一下,Mockito 是命名自一种调酒莫吉托(Mojito),外国人也爱玩谐音梗。。。

3. 在SpringBoot单元测试中使用Mockito

首先在 pom.xml 下新增 spring-boot-starter-test 依赖,该依赖内就有包含了 JUnit、Mockito

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

先写好一个 UserService,他里面有两个方法getUserById()insertUser(),而他们会分别去再去调用 UserDao 这个 bean的getUserById()insertUser()方法

@Component
publicclass UserService {
    @Autowired
    private UserDao userDao;
    public User getUserById(Integer id) {
        return userDao.getUserById(id);
    }
    public Integer insertUser(User user) {
        return userDao.insertUser(user);
    }
}

User model 的定义如下

publicclass User {
    private Integer id;
    private String name;
    //省略 getter/setter
}

如果这时候我们先不使用 Mockito 模拟一个假的 userDao bean,而是真的去调用一个正常的 Spring bean 的 userDao 的话,测试类写法如下。其实就是很普通的注入 userService bean,然后去调用他的方法,而他会再去调用 userDao 取得数据库的数据,然后我们再对返回结果做 assert 断言检查

@RunWith(SpringRunner.class)
@SpringBootTest
publicclass UserServiceTest {
    //先普通的注入一个userService bean
    @Autowired
    private UserService userService;
    @Test
    public void getUserById() throws Exception {
        //普通的使用userService,他里面会再去调用userDao取得数据库的数据
        User user = userService.getUserById(1);
        //检查结果
        Assert.assertNotNull(user);
        Assert.assertEquals(user.getId(), new Integer(1));
        Assert.assertEquals(user.getName(), "John");
    }
}

但是如果 userDao 还没写好,又想先测 userService 的话,就需要使用 Mockito 去模拟一个假的 userDao 出来

使用方法是在 userDao 上加上一个@MockBean注解,当 userDao 被加上这个注解之后,表示 Mockito 会帮我们创建一个假的 mock 对象,替换掉 Spring 中已存在的那个真实的 userDao bean,也就是说,注入进 userService 的 userDao bean,已经被我们替换成假的 mock 对象了,所以当我们再次调用 userService 的方法时,会去调用的实际上是 mock userDao bean 的方法,而不是真实的 userDao bean

当我们创建了一个假的 userDao 后,我们需要为这个 mock userDao 自定义方法的返回值,这里有一个公式用法,下面这段代码的意思为,当调用了某个 mock 对象的方法时,就回传我们想要的自定义结果

Mockito.when( 对象.方法名() ).thenReturn( 自定义结果 )

使用 Mockito 模拟 bean 的单元测试具体实例如下

@RunWith(SpringRunner.class)
@SpringBootTest
publicclass UserServiceTest {
    @Autowired
    private UserService userService;
    @MockBean
    private UserDao userDao;
    @Test
    public void getUserById() throws Exception {
        // 定义当调用mock userDao的getUserById()方法,并且参数为3时,就返回id为200、name为I'm mock3的user对象
        Mockito.when(userDao.getUserById(3)).thenReturn(new User(200, "I'm mock 3"));
        // 返回的会是名字为I'm mock 3的user对象
        User user = userService.getUserById(1);
        Assert.assertNotNull(user);
        Assert.assertEquals(user.getId(), new Integer(200));
        Assert.assertEquals(user.getName(), "I'm mock 3");
    }
}

Mockito 除了最基本的Mockito.when( 对象.方法名() ).thenReturn( 自定义结果 ),还提供了其他用法让我们使用

thenReturn 系列方法

当使用任何整数值调用 userService 的 getUserById() 方法时,就回传一个名字为 I'm mock3 的 user 对象

Mockito.when(userService.getUserById(Mockito.anyInt())).thenReturn(new User(3, "I'm mock"));
User user1 = userService.getUserById(3); // 回传的user的名字为I'm mock
User user2 = userService.getUserById(200); // 回传的user的名字也为I'm mock

限制只有当参数的数字是 3 时,才会回传名字为 I'm mock 3 的 user 对象

Mockito.when(userService.getUserById(3)).thenReturn(new User(3, "I'm mock"));
User user1 = userService.getUserById(3); // 回传的user的名字为I'm mock
User user2 = userService.getUserById(200); // 回传的user为null

当调用 userService 的 insertUser() 方法时,不管传进来的 user 是什麽,都回传 100

Mockito.when(userService.insertUser(Mockito.any(User.class))).thenReturn(100);
Integer i = userService.insertUser(new User()); //会返回100

thenThrow 系列方法

当调用 userService 的 getUserById() 时的参数是 9 时,抛出一个 RuntimeException

Mockito.when(userService.getUserById(9)).thenThrow(new RuntimeException("mock throw exception"));
User user = userService.getUserById(9); //会抛出一个RuntimeException

如果方法没有返回值的话(即是方法定义为public void myMethod() {...}),要改用 doThrow() 抛出 Exception

Mockito.doThrow(new RuntimeException("mock throw exception")).when(userService).print();
userService.print(); //会抛出一个RuntimeException

verify 系列方法

检查调用 userService 的 getUserById()、且参数为3的次数是否为1次

Mockito.verify(userService, Mockito.times(1)).getUserById(Mockito.eq(3)) ;

验证调用顺序,验证 userService 是否先调用 getUserById() 两次,并且第一次的参数是 3、第二次的参数是 5,然后才调用insertUser() 方法

InOrder inOrder = Mockito.inOrder(userService);
inOrder.verify(userService).getUserById(3);
inOrder.verify(userService).getUserById(5);
inOrder.verify(userService).insertUser(Mockito.any(User.class));

4. Mockito的限制

上述就是 Mockito 的 mock 对象使用方法,不过当使用 Mockito 在 mock 对象时,有一些限制需要遵守

  • 不能 mock 静态方法
  • 不能 mock private 方法
  • 不能 mock final class

因此在写代码时,需要做良好的功能拆分,才能够使用 Mockito 的 mock 技术,帮助我们降低测试时 bean 的耦合度

5. 总结

Mockito 是一个非常强大的框架,可以在执行单元测试时帮助我们模拟一个 bean,提高单元测试的稳定性

并且大家可以尝试在写代码时,从 mock 测试的角度来写,更能够写出功能切分良好的代码架构,像是如果有把专门和外部服务沟通的代码抽出来成一个 bean,在进行单元测试时,只要透过 Mockito 更换掉那个 bean 就行了

到此这篇关于SpringBoot单元测试框架Mockito介绍及使用的文章就介绍到这了,更多相关SpringBoot Mockito内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SpringBoot单元测试框架Mockito介绍及使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SpringBoot单元测试框架Mockito介绍及使用

与集成测试将系统作为一个整体测试不同,单元测试更应该专注于某个类。所以当被测试类与外部类有依赖的时候,尤其是与数据库相关的这种费时且有状态的类,很难做单元测试。但好在可以通过“Mockito”这种仿真框架来模拟这些比较费时的类,从而专注于测试某个类内部的逻辑
2023-01-04

Android单元测试框架Robolectric3.0介绍(一)

一、关于Robolectric3.0文章中的所有代码在此:https://github.com/geniusmart/LoveUT,由于Robolectric3.0和3.1版本(包括后续3.x版本)差异不小,该工程中包含这两个版本对应的测试
2022-06-06

Android单元测试框架Robolectric3.0介绍(1)

一、关于Robolectric3.0作为一个软件开发攻城狮,无论你多不屑多排斥单元测试,它都是一种非常好的开发方式,且不谈TDD,为自己写的代码负责,测试自己写的代码,在自己力所能及的范围内提高产品的质量,本是理所当然的事情。那么如何测试自
2022-06-06

怎么在SpringBoot中使用Mockito单元测试

这期内容当中小编将会给大家带来有关怎么在SpringBoot中使用Mockito单元测试,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Mock 测试Mock 测试就是在测试过程中,创建一个假的对象,避免你
2023-06-15

gtest单元测试框架如何使用

使用gtest单元测试框架,需要按照以下步骤:下载并安装gtest框架:可以从https://github.com/google/googletest 下载并编译安装gtest框架。将生成的gtest库和头文件包含到项目中。创建测试文件:在
2023-10-21

NodeJs下的测试框架Mocha的简单介绍

介绍和代码下载 Mocha在2011年发布,是目前最为流行的javascript框架之一,在本文我们重点介绍它在NodeJs上的使用。 如果你需要下载实例代码,可以通过去官网查找。https://mochajs.org/ 下载代码后安装依赖
2022-06-04

如何使用单元测试框架对 Golang 函数进行测试?

go 中使用单元测试框架进行单元测试:导入 testing 包。编写以 test 为前缀的单元测试函数。使用断言函数(如 assertequal())验证测试结果。运行单元测试(go test),验证函数的正确性。如何使用单元测试框架对 G
如何使用单元测试框架对 Golang 函数进行测试?
2024-04-16

C#中如何使用单元测试框架进行自动化测试

C#中如何使用单元测试框架进行自动化测试引言:在软件开发过程中,自动化测试是一个非常重要的环节。通过编写和运行测试代码,可以帮助我们验证和确保代码的正确性和稳定性。在C#开发中,我们可以使用单元测试框架来实现自动化测试。本文将介绍C#中常用
2023-10-22

常用的c++单元测试框架有哪些

常用的C++单元测试框架有以下几个:1. Google Test:由Google开发的C++单元测试框架,功能强大且易于使用,支持参数化测试、断言、测试夹具等功能。2. Catch2:轻量级的C++单元测试框架,易于学习和使用,支持自动发现
2023-10-27

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录