SpringBoot整合JUNIT5单元测试+Mockito

目录

  • 第一章、快速了解JUnit单元测试
    • 1.1)单元测试是什么
    • 1.2)为什么使用JUnit单元测试
  • 第二章、快速使用JUnit5框架
    • 2.1)在pom文件中导入依赖
    • 2.2)新建测试类
    • 2.3)新建一个简单的测试方法
  • 第三章、测试框架提供的注解和方法介绍
    • 3.1)注解
      • 3.1.1)注释测试类
      • 3.1.2)注释成员变量
    • 3.2)方法
      • 3.2.1)Mockito方法
      • 3.2.2)Assert结果断言、verify行为验证
    • 3.3)
  • 第四章、使用Mockito的实例
    • 4.1)需要测试的方法
    • 4.2)测试上面的方法
    • 4.3)

友情提醒:
先看文章目录,大致了解文章知识点结构,点击文章目录可直接跳转到文章指定位置。
三连提问:单元测试是什么?springboot中怎么使用单元测试 ?工作中怎么写单元测试?

第一章、快速了解JUnit单元测试

1.1)单元测试是什么

单元测试:针对方法(最小功能单元)的测试,由程序员自己写。
JUnit是什么:一种帮助我们编写测试的标准测试框架。

1.2)为什么使用JUnit单元测试

不使用单元测试时,我们测试一个方法能否成功运行,我们会在主方法里调用这个方法,看看控制台的运行结果。

public class Test {
    public static void main(String[] args) {
        System.out.println(Test(1));
    }
    public static int Test(int i){
        return ++i;
    }
}

或者更直接的把需要测试代码放到主方法里,看能不能运行成功。

public class Test {
    public static void main(String[] args) {
            System.out.println("test");
    }
}

局限性:但是使用这种方式测试代码局限性很大,比如只有一个main方法无法有组织有层次的测试不同的方法。比如测试的输出结果不够直观。所以我们需要专门的JUnit来编写单元测试

第二章、快速使用JUnit5框架

IDE工具为IDEA

2.1)在pom文件中导入依赖

SpringBoot的spring-boot-starter-test包中,默认集成了JUnit5依赖包,Mockito: Java Mock框架依赖,AssertJ流式断言依赖包等,所以正常来说我们不需要再导入关于单元测试的依赖包了。

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

版本关系如图:对静态类进行mock的时候:mockito-core的版本要在3.4以上。

在这里插入图片描述

2.2)新建测试类

①查看扫描路径是否正确(如果不正确需要手动添加):File-project structure–>moudles–>选中想要的模块–>Sources–>test下的java文件夹右击设置为tests

在这里插入图片描述

②选中需要测试的service包中类的类名,右键选择Generate

在这里插入图片描述

③然后选择Test

在这里插入图片描述

④勾选以下的选项:
1、选择JUnit5。
2、测试类的命名规范为BidInfoServiceImpl类名后面加Test也就是BidInfoServiceImplTest。3、我们需要在test包下建立相同的路径
4、勾选setUp/@Before
5、勾选需要测试的方法
6、选择OK

在这里插入图片描述

⑤查看test下的路径,已经替我们生成了对应的测试类了

在这里插入图片描述

2.3)新建一个简单的测试方法

①我现在想要测试BidInfoServiceImpl类中的fact方法

public class BidInfoServiceImpl implements BidInfoService {
 public int fact(int i){
        int a=++i;
        return a;
    }
}

②在刚刚新建的测试类BidInfoServiceImplTest上面使用@SpringBootTest注解,使用@InjectMock注释在要测试的实现类上,使用@Test注释在测试的方法上

package com.bjpowernode.money.service;

import com.bjpowernode.money.mapper.BidInfoMapper;

/**
 * Tesr for {@link BidInfoServiceImpl}
 * @author bms
 * @since 1.0
 */

// 在junit4的时候使用@Runwith注解,在junit5的时候使用@SpringBootTest注解,
//作用是加载web Application Context并提供Mock Web Environment
@SpringBootTest
//@RunWith(MockitoJUnitRunner.class)
public class BidInfoServiceImplTest {
    @InjectMocks
    BidInfoServiceImpl bidInfoServiceImpl;

    @Test
    public void testFact(){
//第一个参数是预期结果:2。第二个参数是需要测试的方法,传入值1
        assertEquals(2,bidInfoServiceImpl.fact(1));
        assertEquals(4,bidInfoServiceImpl.fact(3));
    }
}

③右键红框处,点击RUN运行,assertEquals()方法中第一个参数是预期结果2。第二个参数是需要测试的方法,传入参数1
在这里插入图片描述
④测试通过(即结果与预期相符),会出现如下提示:
在这里插入图片描述

第三章、测试框架提供的注解和方法介绍

3.1)注解

3.1.1)注释测试类

@SpringBootTest()

@RunWith(SpringRunner.class)

3.1.2)注释成员变量

方式一:

@InjectMock|@Mock:

@InjectMock:注释的是要测试的实现类,不是接口

@Mock:注释测试类serviceimpl用@Autowired引入的成员变量(mock后真实的方法不再调用)

但用Mockito.when(service.方法名(参数)).thenCallRealMethod();还是可以调真实的方法

@Spy:注释测试类serviceimpl用@Autowired引入的成员变量(spy真实的调用不调用要看写法)

但用Mockito.doReturn(“不执行此方法”).when(service).方法名(参数);还是可以不调用真实的方法

@Spy 会真实的执行对象的方法(如果方法报错,test直接报错)

@Mock 不会执行对象的方法(即使方法报错,test只会使用你设置的返回值,不影响流程)

方式二:

@Autowired| ReflectionTestUtils.setField();

@Autowired注释被注入mock的被测试的类

AopTestUtils.getTargetObject()、AopTestUtils.getUltimateTargetObject()

ReflectionTestUtils.setField();将其他的mock对象注入被测试的类中

@Autowired和@InjectMock最好不要一起使用,如果一起使用了

a、必须在test之前@Before中执行 MockitoAnnotations.openMocks(this);对mock初始化

b、测试的时候要用this.serviceimpl.方法名()测试 否则mock还会走真实的方法

3.2)方法

3.2.1)Mockito方法

Mockito.when(service.方法名(参数)).thenReturn(要返回的值);
Mockito.when(service.方法名(参数)).thenCallRealMethod();
Mockito.when(service.方法名(参数)).thenThrow(new RuntimeException());
Mockito.doNothing().when(service).方法名(参数);
Mockito.doReturn(“不执行此方法”).when(service).方法名(参数);
new 对象的:MockedConstruction
静态方法:MockedStatic

3.2.2)Assert结果断言、verify行为验证

assertEquals(expected, actual)是最常用的测试方法
assertTrue(): 期待结果为true
assertFalse(): 期待结果为false
assertNotNull(): 期待结果为非null
assertArrayEquals(): 期待结果为数组并与期望数组每个元素的值均相等

3.3)

第四章、使用Mockito的实例

4.1)需要测试的方法

需要进行测试的方法

@Component
@RequestMapping(path = "/BidInfoService")
public class BidInfoServiceImpl implements BidInfoService {

    @Autowired
    BidInfoMapper bidInfoMapper;

    @Autowired(required = false)
    RedisTemplate redisTemplate;


    // 累计成交额:总金额
    @Override
    @GetMapping("/queryBidMoneySum")
    @ResponseBody
    public Double queryBidMoneySum() {
        //通过工具类常量对应的值,获得展示值
Double bidMoneySum = (Double) redisTemplate.opsForValue().get(Constants.BID_MONEY_SUM);
        if (bidMoneySum != null) {
            return bidMoneySum;
        }
        if (bidMoneySum == null) {
            //如果缓存中值不存在,访问数据库得到值
            bidMoneySum = bidInfoMapper.selectBidMoneySum();
            if (bidMoneySum != null) {
                //将从数据库获得的值设置到缓存,有效时间42秒
redisTemplate.opsForValue().set(Constants.BID_MONEY_SUM, bidMoneySum, 42, TimeUnit.SECONDS);
            } else {
redisTemplate.opsForValue().set(Constants.BID_MONEY_SUM, null, 42, TimeUnit.SECONDS);
            }
        }
        return bidMoneySum;
    }

4.2)测试上面的方法

每一行都详细写了注释,认真看就知道怎么用咯

package com.bjpowernode.money.service;


/**
 * Tesr for {@link BidInfoServiceImpl}
 * @author bms
 * @since 1.0
 */

// 在junit4的时候使用@Runwith,在junit5的时候使用@SpringBootTest,
//作用是加载web Application Context并提供Mock Web Environment
@RunWith(MockitoJUnitRunner.class)
public class BidInfoServiceImplTest {
    //把要测试的类通过mock注入
    @InjectMocks
    BidInfoServiceImpl bidInfoServiceImpl;
    //在运行时,需要用到的对象,使用@mock造个假对象
    @Mock
    RedisTemplate redisTemplate;
    //在运行时,需要用到的对象,使用@mock造个假对象
    @Mock
    BidInfoMapper bidInfoMapper;


    @Test
    public void testQueryBidMoneySum(){
        //缓存不为空的情况:
        //造一个假的值
        ValueOperations value = mock(ValueOperations.class);
        //redisTemplate调用opsForValue,获得(返回)这个mock值
        when(redisTemplate.opsForValue()).thenReturn(value);
        //获得这个mock值value后,调用get方法。得到返回值是5.345
        when(value.get(Constants.BID_MONEY_SUM)).thenReturn(5.345);
        //本类的对象调用需要测试的方法queryBidMoneySum,期望返回值是5.345
        assertEquals(5.345, bidInfoServiceImpl.queryBidMoneySum());

        //缓存为空的情况
        when(redisTemplate.opsForValue()).thenReturn(value);
        //获得这个mock值value后,调用get方法。得到返回值是null
        when(value.get(Constants.BID_MONEY_SUM)).thenReturn(null);
        //当返回值是null,执行selectBidMoneySum去数据库查询,得到返回值是8.88
        when(bidInfoMapper.selectBidMoneySum()).thenReturn(8.88);
        //将从数据库获得的值设置到缓存,有效时间42秒。 因为没有返回值所以使用doNothing().when(value)
        doNothing().when(value).set(Constants.BID_MONEY_SUM, 8.88, 42, TimeUnit.SECONDS);
        //本类的对象调用需要测试的方法queryBidMoneySum,期望返回值是8.88
        assertEquals(8.88, bidInfoServiceImpl.queryBidMoneySum());
    }

4.3)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/299628.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【设计模式】备忘录模式

一起学习设计模式 目录 前言 一、概述 二、结构 三、案例实现 1、 “白箱”备忘录模式 2、“黑箱”备忘录模式 四、优缺点 五、使用场景 总结 前言 【设计模式】备忘录模式——行为型模式。 一、概述 备忘录模式提供了一种状态恢复的实现机制&#xff0c;使得用户可以…

Android studio BottomNavigationView 应用设计

一、新建Bottom Navigation Activity项目: 二、修改bottom_nav_menu.xml: <itemandroid:id="@+id/navigation_beijing"android:icon="@drawable/ic_beijing_24dp"android:title="@string/title_beijing" /><itemandroid:id="@+i…

小游戏实战丨基于PyGame的消消乐小游戏

文章目录 写在前面PyGame消消乐注意事项系列文章写在后面 写在前面 本期内容&#xff1a;基于pygame实现喜羊羊与灰太狼版消消乐小游戏 下载地址&#xff1a;https://download.csdn.net/download/m0_68111267/88700193 实验环境 python3.11及以上pycharmpygame 安装pygame…

jenkins忘记admin密码

jenkins忘记admin密码&#xff0c;重置密码&#xff1a; 1.找打jenkins目录下面的config.xml [rootVM-0-15-centos .jenkins]# find ./* -name config.xml ./config.xml [rootVM-0-15-centos .jenkins]# pwd /root/.jenkins删除下面的这部分内容&#xff1a; [rootVM-0-15-c…

Android开发编程从入门到精通,安卓技术从初级到高级全套教学

一、教程描述 本套教程基于JDK1.8版本&#xff0c;教学内容主要有&#xff0c;1、环境搭建&#xff0c;UI布局&#xff0c;基础UI组件&#xff0c;高级UI组件&#xff0c;通知&#xff0c;自定义组件&#xff0c;样式主题&#xff1b;2、四大组件&#xff0c;Intent&#xff0…

【UML】第15篇 状态机图

目录 一、状态机图的定义 二、应用场景 三、绘图符号的说明 四、语法 五、例图 一、状态机图的定义 状态机图&#xff08;State Machine Diagram&#xff09;是UML中的一种行为图&#xff0c;它描述了一个对象在其生命周期内的状态变化。状态机图通过展示对象在不同状态下…

技术学习|CDA level I 描述性统计分析(数据的描述性统计分析)

技术学习|CDA level I 描述性统计分析&#xff08;数据的描述性统计分析&#xff09; 数据的描述性统计分析常从数据的集中趋势、离散程度和分布形态3个方面进行。 一、集中趋势 集中趋势是指数据向其中心值靠拢的趋势。测量数据的集中趋势&#xff0c;主要是寻找其中心值。…

跨站脚本攻击漏洞XSS绕过22种方式总结

XSS漏洞简介 跨站脚本攻击在目前这个时间节点还是属于一个排位比较高的漏洞&#xff0c;在OWASP TOP10 2021中隶属于注入型漏洞&#xff0c;高居TOP3的排位&#xff0c;可见这个漏洞的普遍性。跨站脚本攻击的学习中我们主要需要明白的是跨站的含义&#xff0c;以及XSS的核心。…

Vue3-39-路由-导航异常的检测 afterEatch 与 编程式导航之后的订阅动作

说明 本文主要是介绍一下 路由的后置守卫 afterEatch 的一个重要的作用 &#xff1a; 就是检测路由异常信息。 它的实现方式是 通过第三个参数来返回的。 而且&#xff0c;它的异常检测是全局的。导航的异常有以下三种类型&#xff1a; aborted : 在导航守卫中 被拦截并返回了…

1月最新阿里云服务器租用价格表_轻量61元_ECS99元一年

2024年1月最新阿里云服务器租用价格表&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;2核4G4M带宽轻量服务器一年165元12个月、2核4G服务器30元3个月&#xff0c;云服务器ECS可以选择经济型e实例、通用…

学习笔记——C++运算符之算术运算符

C中运算符包含诸多种类&#xff0c;其中有&#xff1a;算术运算符&#xff0c;赋值运算符&#xff0c;比较运算符和逻辑运算符 每一种运算符及其作用如下表所示&#xff1a; 一&#xff0c;算术运算符1&#xff0c;加减乘除 其中&#xff0c;“”&#xff0c;“-”运算符既可…

QT上位机开发(数据库sqlite编程)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 编写软件的时候&#xff0c;如果用户的数据比较少&#xff0c;那么用json保存是非常方便的。但是一旦数据量大了之后&#xff0c;建议还是用数据库…

编程语言的未来:贴近人类、灵活高效与探索无限

编程语言的未来&#xff1f; 在当今的科技潮流中&#xff0c;编程语言是至关重要的一环&#xff0c;更是赋能科技行业的基础工具。我深信&#xff0c;未来的编程语言可能将朝着更贴近人类、灵活高效和面向无限可能的方向发展。 人性化是我预期的第一个趋势。未来的编程语言将…

如何解决找不到mfc100u.dll无法运行程序问题,分享四种靠谱的方法

在日常使用电脑的过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中之一就是找不到mfc100u.dll的困扰。这个问题主要是因为mfc100u.dll是Microsoft Foundation Class&#xff08;MFC&#xff09;库中的一个版本特定的DLL文件&#xff0c;它是Visual Studio 2010及更早…

轻松识别几个小时的长音视频文件

前言 之前的文章绍一个准确率非常高的语音识别框架&#xff0c;但那个只能识别实时的短音频&#xff0c;如果想要识别一个非常长的音频&#xff0c;几十分钟&#xff0c;甚至几个小时&#xff0c;那之前的那个是做不到的所以就有了本文。本文介绍搭建一个长语音识别服务&#…

LeetCode刷题:面试题 02.01. 移除重复节点

题目&#xff1a; 是否独立完成&#xff1a;算是&#xff0c;但是使用自己的办法时间复杂度会超标 解题思路&#xff1a; 1.双循环嵌套&#xff0c;定义快慢节点&#xff0c;双层嵌套循环&#xff0c;如果值一样则剔除&#xff0c;但是时间复杂度为O&#xff08;n&#xff09;…

深度卷积生成对抗网络(DCGAN)|完整代码实现

生成对抗网络&#xff08;GAN&#xff09;由Ian Goodfellow在2014年提出。GAN通过训练两个神经网络解决了非监督问题。这两个网络一个称为生成网络&#xff0c;一个称为判别网络。 事实上&#xff0c;该网络的训练过程很有趣。我们可以借助一个例子来理解。最初&#xff0c;伪…

强化学习的数学原理学习笔记 - RL基础知识

文章目录 Roadmap&#x1f7e1;基础概念贝尔曼方程&#xff08;Bellman Equation&#xff09;基本形式矩阵-向量形式迭代求解状态值 vs. 动作值 &#x1f7e1;贝尔曼最优方程&#xff08;Bellman Optimality Equation&#xff0c;BOE&#xff09;基本形式迭代求解 参考资料&…

服务器不稳定是什么意思?有哪些表现

在当今的信息化时代&#xff0c;服务器已经成为企业和组织不可或缺的基础设施。然而&#xff0c;由于各种原因&#xff0c;服务器可能会出现不稳定的情况&#xff0c;给企业和组织带来不必要的损失和风险。那么&#xff0c;什么是服务器不稳定&#xff0c;它又有哪些表现呢&…

35岁的程序员,见到领导就躲,害怕跟领导沟通,你被说中了吗?

35岁的程序员&#xff0c;见到领导就躲&#xff0c;害怕跟领导沟通&#xff0c;你被说中了吗&#xff1f; 35岁的小王是一名项目经验丰富、解决问题能力强的资深程序员&#xff0c;然而却唯独有一个软肋&#xff1a;害怕碰见领导&#xff0c;害怕跟领导沟通。 我们不经要问&a…