9、测试Service组件和使用模拟组件辅助测试

news2024/11/18 7:45:07

测试Service组件和使用模拟组件辅助测试

测试Service组件

测试Service组件无需启动Web服务器,所以使用@SpringBootTest(webEnvironment = WebEnvironment.NONE)修饰测试用例类即可
(用NONE表示不启动Web服务器)。

Service组件其实就是一个普通的组件,它不需要借助于Web服务器,也不需要启动模拟Web环境
测试用例类定义接受依赖注入的Service类型的实例变量,然后通过该变量测试Service组件的方法

【Spring Boot提供支持就是】:将被测试的组件(Service)注入到测试用例中

在Spring Boot应用中,测试所有的普通组件都可以使用该方式

1、测试添加书籍的方法
两种方式:
方式一:通过 @ParameterizedTest + @MethodSource 注解的方式来测试
方式二:通过 @ParameterizedTest + @CsvSource注解 方式
在这里插入图片描述
代码示例:

    //测试Service添加书籍的方法---用参数测试的注解
    //通过 @ParameterizedTest + @MethodSource 注解的方式来测试
    @ParameterizedTest
    //这个注解是通过一个 getBooks 的方法的返回值来为这个测试方法传入参数,getBooks这个方法必须是静态Static修饰的,而且返回的值必须是Stream类型
    @MethodSource(value = "getBooks")
    public void testAddBook(Book book){
        bookService.addBook(book);
    }
    //因为要测试的方法需要的参数是一个Book对象,可以使用@MethodSource(value = "getBooks")注解来尝试
    //getBooks这个方法必须是静态Static修饰的,而且返回的值必须是Stream类型
    public static Stream<Book> getBooks(){
        //通过Stream流来创建数据
        Stream<Book> bookStream = Stream.of(new Book("aaa", new BigDecimal(100), "ljh1"),
                new Book("bbb", new BigDecimal(110), "ljh2"),
                new Book("ccc", new BigDecimal(120), "ljh3"));
        return bookStream;
    }



    //用旧的 @ParameterizedTest + @CsvSource注解 方式
    @ParameterizedTest //允许测试方法接收参数进行测试,和注解 @CsvSource 一起使用,@CsvSource注解用来写参数数据
    //参数是一个数组,数组里面的每一个元素就是方法的参数
    @CsvSource({"书籍A1,100,ljh", "书籍B2,110,ljh", "书籍C3,120,ljh"})
    public void testAddBook02(String name,BigDecimal price,String author){
        Book book = new Book(name, price, author);
        bookService.addBook(book);
    }

测试查询书籍的方法
这个就很普通了

    //测试Service查询书籍的方法
    @Test
    public void testGetAllBooks(){
        List<Book> allBooks = bookService.getAllBooks();
        allBooks.forEach(book -> System.err.println(book));
    }

测试删除书籍的方法,因为需要用到参数id,所以需要使用到这两个注解
@ParameterizedTest //表示这个测试方法是参数测试
@ValueSource(ints = {94,95,96}) //这个注解通过int类型的数组中的元素来作为参数

    //测试Service删除书籍的方法
    @ParameterizedTest
    @ValueSource(ints = {94,95,96})
    public void testDeleteBookById(Integer id){
        bookService.deleteBookById(id);
    }

借助于模拟组件来完成测试

假设要测试的A组件依赖于B组件,但B组件可能根本就没有开发完成,或B组件开发出来了,但没有经过严格的测试。
如果直接对A组件进行测试,此时可能测试出现的错误并不是A组件导致的,而是A组件所依赖的B组件所导致的。
为了避免B组件将错误传给A组件,或者在没有B组件的前提下,能对A组件进行测试
此时就需要提供一个B组件的模拟对象——借助于Mockit即可。

简单来说,service 层依赖 Dao层,我们在测试的时候,如果Dao还没开发,就测试不了,或者说测试的时候出Bug,但是不知道是service层出错还是Dao层出错。

这个时候就需要借助模拟对象 Mockit 来测试了。弄一个假的Dao组件。

使用模拟组件测试Service组件的查询书籍的方法

涉及注解:
@MockBean :声明被修饰的组件将作为模拟组件,而不去使用真实组件,就是这个 bookDao 是模拟出来的,不是正式的 dao 层。

主要点:
BDDMockito.given(this.bookDao.findAll()).willReturn(list);

BDDMockito 定义模拟组件(bookDao)的指定方法(findAll())的返回值(list)
.given() 调用BDDMockito的given()类方法为模拟组件的指定方法直接设置返回值
this.bookDao 就是上面声明的用@MockBean假装注入的bookDao假组件
findAll() 就是我们待会访问的添加书籍的方法
willReturn(list) 就是我们给这个findAll()方法的返回值。

(1)定义一个@MockBean修饰的模拟组件
——该模拟组件就代表了被依赖组件(该组件可能未开发完成,或未经过严格测试)

(2)在测试方法中,调用BDDMockito的given()类方法为模拟组件的指定方法直接设置返回值。
——这样即可基于对模拟组件所设置的返回值来进行测试。


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class BookServiceMockBeanTest {

    @Autowired
    private BookService bookService;

    @MockBean  //声明被修饰的组件将作为模拟组件,不使用真实组件,就是这个 bookDao 是模拟出来的,不是正式的 dao 层。
    private BookDao bookDao;


    //测试Service查询书籍的方法
    @Test
    public void testGetAllBooks() {
        //假数据
        List<Book> list = new ArrayList<>();
        list.add(new Book("zzz", new BigDecimal(100), "ljh1"));
        list.add(new Book("xxx", new BigDecimal(110), "ljh2"));
        list.add(new Book("vvv", new BigDecimal(120), "ljh3"));

        //BDDMockito 定义模拟组件(bookDao)的指定方法(findAll())的返回值(list)
        //this.bookDao 就是上面声明的用@MockBean假装注入的bookDao假组件
        //.findAll()  就是我们待会访问的添加书籍的方法
        //.willReturn(list) 就是我们给这个findAll()方法的返回值。
        BDDMockito.given(this.bookDao.findAll()).willReturn(list);

        //这个getAllBooks()方法就变成了依赖模拟组件来实现,而不会去调用真实的业务方法。getAllBooks()返回的数据从原本的真实的数据变成了上面模拟组件提供的数据willReturn(list)
        List<Book> allBooks = bookService.getAllBooks();

        //断言测试,看返回成功的值是不是假数据。
        //此处的断言与真实的Dao组件是无关的,它只依赖与模拟的Dao组件。
        Assertions.assertEquals("zzz",allBooks.get(0).getName());
        Assertions.assertEquals("xxx",allBooks.get(1).getName());
        Assertions.assertEquals("vvv",allBooks.get(2).getName());
    }
  }

使用模拟组件测试添加书籍的方法

    //使用模拟组件测试添加书籍的方法
    @ParameterizedTest
    @MethodSource(value = "getBooks")
    public void testAddBook(Book book) {
        Book b = new Book(12345, "ggg", new BigDecimal(111), "lll");
        //BDDMockito指定this.bookDao模拟组件的save()方法返回的数据是b
        BDDMockito.given(this.bookDao.save(book)).willReturn(b);
        Integer id = bookService.addBook(book);
        //断言
        Assertions.assertEquals(12345,id);
    }

    public static Stream<Book> getBooks() {
        //通过Stream流来创建数据
        Stream<Book> bookStream = Stream.of(
                new Book("aaa", new BigDecimal(100), "ljh1"),
                new Book("bbb", new BigDecimal(110), "ljh2"),
                new Book("ccc", new BigDecimal(120), "ljh3")
        );
        return bookStream;
    }

删除书籍的方法没法测试,就没有测试了

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【002 操作系统】进程的状态及状态转换图?

一、进程的状态 1. 创建状态 2. 就绪状态 3. 运行状态 4. 阻塞状态 5. 终止状态 图源&#xff1a;进程、线程基础知识全家桶&#xff0c;30 张图一套带走_Linux_小林coding_InfoQ写作社区 NULL -> 创建状态&#xff1a;一个新进程被创建时的第一个状态&#xff1b; 创建状态…

python+django+mysql项目实践一(环境准备)

python项目实践 环境说明: Pycharm 开发环境 Django 前端 MySQL 数据库 Navicat 数据库管理 创建Pycharm项目 安装Django 在pycharm文件—设置进行安装 新建Django项目 注意项目创建目录 项目默认目录文件说明: __init__.py asgi.py 【异步接受网络…

Qt 5. QSerialPort串口收发

1. 代码 //ex2.cpp #include "ex2.h" #include "ui_ex2.h" #include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo>int static cnt 0;Ex2::Ex2(QWidget *parent): QDialog(parent), ui(new Ui::Ex2) {ui->setupUi…

Win11的dev通道更新Build23493版本后启用Windows Copilot的解决办法

博客嘛&#xff0c;多偷懒少打字&#xff0c;先上图&#xff1a; 首先是微软宣布了对dev通道版本推送了Windows Copilot for Windows 11&#xff0c;但是相信像我这样的小白想体验又对win一窍不通的人应该也有不少&#xff0c;经历了一次重装&#xff0c;五次版本的回退再更新后…

opencv rtsp 硬件解码

讨论使用opencv的reader 硬件解码的方案有太多种&#xff0c;如果使用ffmpeg硬件解码是最方便的&#xff0c;不方便的是把解码过后的GPU 拉到 CPU 上&#xff0c;再使用opencv的Mat 从cpu 上上载到gpu上&#xff0c;是不是多了两个过程&#xff0c;应该是直接从GPU mat 直接去…

从Bean的生命周期分析Dubbo的源码

写作目的 Dubbo作为RPC中的经典落地实践&#xff0c;作为阿里内部目前还是大规模使用的基础框架&#xff0c;作为CRUD的底层。无论从什么角度来看简单的阅读一下Dubbo的源码还是有必要的。 前提&#xff1a;要了解Bean的生命周期 源码下载 gitee源码下载 源码分析 开启Dub…

《MySQL 实战 45 讲》课程学习笔记(四)

深入浅出索引 索引的出现其实就是为了提高数据查询的效率&#xff0c;就像书的目录一样。 索引的常见模型 哈希表 哈希表是一种以键 - 值&#xff08;key-value&#xff09;存储数据的结构&#xff0c;我们只要输入待查找的值即 key&#xff0c;就可以找到其对应的值即 Val…

时序分析:曲线分解

以下仅为博主个人观点&#xff0c;如有错误欢迎批评指正。 前言后记都挺重要建议还是看一下吧。 文章目录 前言经验模态分解EMDEEMDCEEMDAN 变分模态分解VMD 奇异谱分析SSA 后记 前言 本篇文章将会介绍常用曲线分解方法(经验模态分解及其变种&#xff0c;变分模态分解&#x…

集团企业网站建设开发

为集团提供一个互联网上的形象宣传和信息发布、收集的重要平台 利用最新的互联网动态数据库交互能力&#xff0c;建立一套在互联网上具有领先地位的集团网站&#xff0c;将集团和子公司网站做到有机的统一。集团网站不但要把集团的企业、产品等相关信息展示给我们的客户、合作…

RabbitMQ 教程 | 第2章 RabbitMQ 入门

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

1,复杂度和简单排序算法【p2-p3】

复杂度和简单排序算法 1&#xff0c;时间复杂度1.1选择排序1.2冒泡排序1.3异或运算1.3.1性质&#xff1a;1.3.2案例例1例2 1.4插入排序1.5二分法1.5.1在一个有序数组中&#xff0c;找某个数是否存在1.5.2在一个有序数组中&#xff0c;找>某个数最左侧的位置1.5.3局部最小值问…

linux系统编程重点复习--守护进程和线程

复习目标 说出守护进程的特点独立完成守护进程的创建独立实现多个线程的创建独立实现线程的退出和资源回收理解线程同步的思想 1 守护进程 1.1 守护进程介绍 Daemon(精灵)进程&#xff0c;是Linux中的后台服务进程&#xff0c;通常独立于控制终端并且周期性地执行某种任务或…

通向架构师的道路之Apache整合Tomcat

一、先从J2EE工程的通用架构说起 这是一个通用的Web即B/S工程的架构&#xff0c;它由&#xff1a; Web Server App Server DB Server 三大部分组成&#xff0c;其中&#xff1a; Web Server 置于企业防火墙外&#xff0c;这个防火墙&#xff0c;大家可以认为是…

hugging face下载数据集

开始直接执行这个&#xff0c;下载下来的图片打不开 git clone https://huggingface.co/datasets/diffusers/dog-example 解决办法&#xff1a; 安装git lfs 1. curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash 2. sudo apt…

论文笔记:Adjusting for Autocorrelated Errors in Neural Networks for Time Series

2021 NIPS 原来的时间序列预测任务是根据预测论文提出用一阶自回归误差预测 一阶差分&#xff0c;类似于ResNet的残差思路&#xff1f;记为pred&#xff0c;最终的预测结果

zore-shot,迁移学习和多模态学习

1.zore-shot 定义&#xff1a;在ZSL中&#xff0c;某一类别在训练样本中未出现&#xff0c;但是我们知道这个类别的特征&#xff0c;然后通过语料知识库&#xff0c;便可以将这个类别识别出来。概括来说&#xff0c;就是已知描述&#xff0c;对未知类别&#xff08;未在训练集中…

Qsys介绍

文章目录 前言一、为什么需要Qsys1、简化了系统的设计流程2、Qsys涉及的技术 二、Qsys真身1、一种系统集成工具2、何为Nios II1、内核架构2、Nios II选型 三、Qsys设计涉及到的软件&工具四、总结五、参考资料 前言 Qsys是Altera下的一个系统集成工具&#xff0c;可用于搭建…

代码随想录算法训练营第三十天 | 单调栈系列复习

单调栈系列复习 每日温度未看解答自己编写的青春版重点题解的代码日后再次复习重新写 下一个更大元素 I未看解答自己编写的青春版重点题解的代码日后再次复习重新写 下一个更大元素II未看解答自己编写的青春版重点题解的代码日后再次复习重新写 接雨水未看解答自己编写的青春版…

idea模块的pom.xml被划横线,不识别的解决办法

目录 问题&#xff1a; 解决办法&#xff1a; 1.打开设置 2. 取消勾选 3.点击确认 4.解决 问题提出&#xff1a; 写shi山的过程中&#xff0c;给模块取错名字了&#xff0c;改名的时候不知道点到了什么&#xff0c;一个模块的pom.xml变成灰色了&#xff0…

3ds MAX粒子系统演示

其他各案例可以在视频中看到&#xff1a; 从左向右依次是&#xff1a; 粒子流源、喷射、雪、超级喷射、暴风雪、粒子阵列、粒子云 粒子系统