Mockito单元测试学习笔记(2):Mockito的简单案例_大苏打seven的博客-程序员秘密_mockito 单例

技术标签: Mockito  

本文是自己对学习的一个总结


1、基本Mockito测试的编写

了解到什么是Mockito,并且配置好Mockito的maven之后,我们就可以开始编写一个最基本的Mockito测试类了。如果对这两个内容不太了解,可以查看这篇文章https://blog.csdn.net/sinat_38393872/article/details/106520371。

1.1、确定项目结构

1.1.1、 业务代码的结构

Mockito是在Spring的框架中使用的单元测试,我们先新建一个Spring的项目,项目结构如下所示。
在这里插入图片描述
这是一个典型的Spring项目结构,Service层是我们想要测试的类。Service的代码依赖Dao层的类,我们将在测试中模拟dao层的代码,不让dao层的代码真正执行。

我们先看看StudentServiceImpl的代码

public class StudentServiceImpl implements StudentService {
    
    @Autowired
    private StudentDao studentDao;
	/**
	 * 这是准备测试的代码,其中的studentDao.insert方法我们要模拟执行
	 */
    @Override
    public boolean insert(Integer id) {
    
        if(studentDao.insert(id) >= 1) {
    
            return true;
        }   else {
    
            return false;
        }
    }
}

我们再看看StudentServiceImpl依赖的StudentDao的代码。

public class StudentDao {
    
    public int insert(Integer id) {
    
        System.out.println("执行了真正的操作");
        return 1;
    }
}

额·····这个代码不是真正地操作数据库,先别在意这个。总之,这段代码真正执行的话,应该要在控制台输出"执行了真正的操作"这么一行字,我们等会测试的时候查看控制台有没有输入相应的内容就知道这段代码有没有被真正执行了。




1.1.2、测试代码的项目结构

测试文档的项目结构应该与业务代码的一致。测试类和被测试类的相对位置应该是一样的。同时,测试类的命名建议为”被测试类+Test"。

比如上面的被测试类是StudentService,对应的测试类就是StudentServiceTest。StudentService的目录是com.example.mokitoLearning.student.service.StudentService,StudentServiceTest的目录也是com.example.mokitoLearning.student.service.StudentServiceTest。

除此之外,测试方法的命名也建议是“被测试方法 + Test”。比如我们测试StudentService中的insert方法,那我们的测试方法就应该写在StudentServiceTest之下,方法名为insertTest。





2、编写测试类

2.1 标记被测试的类(@InjectMocks)

确定好项目结构以后,我们在测试类中开始写测试方法。 测试类不会自己知道我们想测试哪个类,所以我们使用@InjectMocks标注一下。

public class StudentServiceTest {
    
    @InjectMocks
    private StudentServiceImpl studentService;
    //其他操作
}

@InjectMocks标注的类型不能是接口,所以我标注的是StudentService的实现类。

2.2 给被测试类注入依赖(@Mock)

被测试类的依赖是需要注入的。我们使用@Mock进行注入。@Mock标记的变量会被注入到@InjectMocks标注的变量中。其用法和@Autowired一样。

public class StudentServiceTest {
    
    @InjectMocks
    private StudentServiceImpl studentService;
    @Mock
    private StudentDao studentDao;
}

2.3 初始化Mockito(@Before和MockitoAnnotations.initMocks(this);)

测试方法执行前,必须先初始化Mockito。初始化Mockito是这样的。

MockitoAnnotations.initMocks(this);

我们现在先别管这里面做了什么,只要知道测试方法执行前,必须先执行这一条语句。

这样的话,每个方法的第一句我们就要先写这么一条语句,这有些麻烦。我们可以利用@Before注解让程序简洁一些。

@Before用来标注一个public void方法,这个被标注的方法会在所有的测试方法运行前运行。通常在@Before标注的方法中定义一些公共逻辑,比如初始化MockitoAnnotations.initMocks(this);就是其中之一。使用@Before后,我们就不用在每一个测试方法中都写初始化Mockito的语句了。

public class StudentServiceTest {
    
    @InjectMocks
    private StudentServiceImpl studentService;
    @Mock
    private StudentDao studentDao;

	/**
	 * 不用在意方法名是什么,只要方法是public void的就可以
	 */
    @Before
    public void init() {
    
        MockitoAnnotations.initMocks(this);
    }
}

另外,我们可以定义多个@Before标注的方法。

2.4 标记测试方法(@Test)

我们使用@Test标记一个方法是测试方法,标记以后这个方法才可以被测试。项目启动时,系统会运行@Test标注的方法,方法中出错的话(逻辑不符合我们的预期),项目会无法启动,这时候我们就能知道项目的代码是有问题的。这样就能帮助我们快速知道问题所在,也能提前知道项目存在问题,避免上线隐患。

public class StudentServiceTest {
    
    @InjectMocks
    private StudentServiceImpl studentService;
    @Mock
    private StudentDao studentDao;

    @Before
    public void init() {
    
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void insertTest() {
    
     	//测试逻辑
    }
}

2.5 模拟依赖

单元测试中,不能真正执行依赖的外部逻辑。我们必须模拟执行。

在Mockito中,我们可以使用

Mockito.when().thenReturn();

这样的语句来模拟依赖逻辑。这个方法应该在测试方法的开始部分就写明。这个方法表示测试逻辑运行时,到了要调用某一个方法的时候,不去执行这个方法,直接返回一个值。我们看看示例。

Mockito.when(studentDao.insert(Mockito.any())).thenReturn(3);

这个语句之后,我们测试执行studentDao的insert方法时,一遇到studentDao.insert()方法时,系统就不会去真正执行这个方法,而是模拟执行,直接返回3。我们还可以设置为不返回值,而是抛出异常。更多的用法可以看官方文档https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#34。

到了这里我们就应该能写出一个基本的测试了。

public class StudentServiceTest {
    
    @InjectMocks
    private StudentServiceImpl studentService;
    @Mock
    private StudentDao studentDao;

    @Before
    public void init() {
    
        MockitoAnnotations.initMocks(this);
    }
    @Test
    public void insertTest() {
    
        Mockito.when(studentDao.insert(Mockito.any())).thenReturn(3);
        //执行到studentDao.insert方法是,直接返回3,那么下面这条语句的断言应该不会报错
        Assert.assertEquals(true, studentService.insert(1));
        System.out.println(studentService.insert(4));
    }
}

执行测试方法,输出结果如下
在这里插入图片描述
没有输出"执行了真正的操作",所以studentDao.insert方法确实没有真正执行,模拟成功。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sinat_38393872/article/details/106539895

智能推荐

接收率高达29%的ICLR 2021有哪些论文入榜呢?_深蓝学院的博客-程序员秘密

​文末可领取ICLR2021深度学习论文集ICLR,全称为International Conference on Learning Representations(国际学习表征会议),2013年由两位深度学习大牛、图灵奖得主 Yoshua Bengio 和 Yann LeCun牵头创办。ICLR成立至今仅七年,但它已被学术研究者们广泛认可,被认为是“深度学习领域的顶级会议”。本次ICLR 2021一共有2997篇有效论文投稿,最后一共 860 篇被接收,录取率达到了 28.7% ,相比.

小程序android图片多变卡,【小程序】优化-解决swiper渲染很多图片时的卡顿_小刀刀不乖的博客-程序员秘密

相信各位在开发的时候应该有遇到这样一个场景,比如商品的图片浏览,有时图片的浏览会很大,多的时候达几百张或上千张,这样就需要swiper里需要很多swiper-item,如此一来渲染的时候就会很消耗性能,渲染时会有一大段的空白时间,有时还会造成卡顿,体验非常差,下面给大家介绍一下我的解决方案。首先是wxml结构:js:主要是利用current属性,swiper里面只放3个swiper-item,要显...

Vue 响应式——模拟封装Vue(二)_Holyforsaken_FHC的博客-程序员秘密

Vue 响应式——模拟封装VueDepDepDep这个类的作用,是收集依赖,发送通知。也就是在data的getter中 添加观察者,以及通知watcher该类有三个成员,一个属性和两个方法:subs 观察者数组addSub 添加观察者方法notify 发送通知class Dep { constructor() { this.subs = [] } // 添加观察者 addSub(sub) { if (sub &&am

简单使用django框架_minhoag的博客-程序员秘密

首先,打开pycharm下的Terminal窗口,安装django框架输入pip install django如下图所示,即安装成功接着,创建一个Django项目(这里的项目名为pyshop),此项目可包含多个应用程序创建成功后,打开项目,可以看到一个package,里面有一些模块可供使用,内容如下:wsgi.py提供一个接口,用于django和web构建的应用程序中。还可以看到有一个manage.py,可管理django项目,可用于启动web服务器,可用于数据库操作

0619_如何成功安装Angular-Cli?踩坑记_Golden_soft的博客-程序员秘密

由于Angular4升级了,旧版的Angular-Cli支持性不是很好,所以Angular-Cli也需要升级更新,本质就是删除掉以前的,再重新安装就好了。Angular-Cli is more than tool,it is a platform!一、安装Angular-Cli经过n次的失败安装,终于在最后一次安装成功,为了使同学们少走弯路,现将经验写下来:1、查看...

️【保姆级安装教程】️使用VMware Workstation搭建Windows11系统上手体验,结尾有趣事_xybDIY的博客-程序员秘密

使用VMware Workstation搭建Windows11系统一、前提准备1、Windows11镜像下载2、虚拟机硬件资源分配3、虚拟机安装注意事项二、安装步骤1、打开VMware Workstation 16 pro软件2、选择“创建新的虚拟机”3、选择“自定义”类型的配置4、选择虚拟机硬件兼容性5、安装客户机操作系统6、选择客户机操作系统7、命名虚拟机8、固件类型选择9、处理器配置10、虚拟机内存大小11、网络类型12、选择I/O控制器类型13、选择磁盘类型14、选择磁盘15、指定磁盘容量16、指定

随便推点

SpringCloud文件上传_web18224617243的博客-程序员秘密_springcloud文件上传解决方案

2.实现图片上传刚才的新增实现中,我们并没有上传图片,接下来我们一起完成图片上传逻辑。文件的上传并不只是在品牌管理中有需求,以后的其它服务也可能需要,因此我们创建一个独立的微服务,专门处理各种上传。2.1.搭建项目2.1.1.创建SpringCloud项目2.1.2.添加依赖我们需要EurekaClient和web依赖:<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/

Android 快别用Toast了,来试试Snackbar_普通网友的博客-程序员秘密

=======Toast提示默认显示在界面底部,使用Toast.setGravity()将提示显示在中间,如下:Toast toast = Toast.makeText(this, str, Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();运行在在Android 12上无法显示,查看Logcat提示如下:Toast: se

uva 514 - Rails(栈)_JeraKrs的博客-程序员秘密

题目链接:uva 514 - Rails题目大意:给定n,表示有一个序列从1到n,问说通过一个栈的转换,可否形成给定序列。解题思路:出现ai−1>ai+1且ai+1>ai的情况就不行。#include #include #include using namespace std;const int maxn = 1005;int N, arr[maxn];boo

[zz]我的openldap经历_asdfsadfsad097097的博客-程序员秘密

转自:http://blog.csdn.net/porcupinefinal/article/details/640523我的openldap经历 ----by [email protected] 转载请注明出处。大致叙述一下。如今网上的ldap的文档,多半是相互抄袭的。全他 *** 狗屁不通,千篇一律。其实ldap主要应用在大容量邮件系统上。几乎所有的文档对这个问题避而

android scrollview源码分析,Android—ScrollView源码分析及简单实现_臭熊的哥哥的博客-程序员秘密

我的CSDN: ListerCi我的简书: 东方未曦一、ScrollView介绍及源码分析ScrollView是Android日常开发中比较常见的一个ViewGroup,它只能有一个子View。用户在滑动时子View在ScrollView内部滚动,显示不同的区域。在开发中如果需要将多个不同类型的视图垂直排列时,我们一般会使用ScrollView。但是永远不要将RecyclerView和ListVi...

flask-socketio:API 参考_Esun_nyy的博客-程序员秘密

flask-socketioAPI 参考类flask_socketio.SocketIO(app=None,**kwargs)创建一个 Flask-SocketIO 服务器。参数: app- flask应用程序实例。如果在实例化此类时不知道应用程序实例,则socketio.init_app(app)在应用程序实例可用时调用。 manage_session– 如果设置为True,此扩展管理 Socket.IO 事件的用户会话。如果设置为False,则使用 ...

推荐文章

热门文章

相关标签