‍我想我大抵是疯了,我喜欢上了写单元测试

news2024/9/20 16:54:41

前言

大家好我是聪。相信有不少的小伙伴喜欢写代码,但是对于单元测试这些反而觉得多此一举,想着我都在接口文档测过了!还要写什么单元测试!写不了一点!!

在这里插入图片描述

由于本人也是一个小小程序猿🙉,我以前也不喜欢写,最近给扔到了另一个 leader 的项目组里面,刚进去他给我下达的命令就是,你写的代码逻辑都要给我写上单元测试,而且要生成覆盖率报告给我!哇!我顿时就难受了,我之前都没有这么严格的,但是呢最近在我疯狂的写单元测试下,我发现我爱上了写单元测试。

单元测试的成长历程

第一次接触单元测试,还是在大学的测试课程里面。老师巴拉巴拉的讲,我虽然能听懂,但是不知道有啥用,课程作业反正做起来也没啥难度,反正能输出完事。

还有些接触单元测试就是平时学习视频的时候,跟着博主教的敲,这种简单的比如测试一个Mybatis 查询功能的单元测试,在我之前看来,soso 我直接用 swagger 文档请求岂不是更方便,代码都不用写咯。
在这里插入图片描述
直到我接触到了公司项目的单元测试,刚来公司看见之前的老项目单元测试都是成堆成堆的写,我也不是很理解,由于老项目的负责员工不知道换了多少代,新负责的都没调试过单元测试,直接代码改动,导致项目现在的单元测试很多环境配置都没及时更新,无法正常启动。当然也没人理会💥。

最近接触单元测试就是来到了新项目组这边的要求,我才重新看清了单元测试的重要性,请听我娓娓道来~

单元测试究竟能干嘛

单元测试究竟能干嘛这个问题时常疑惑着我,毕竟很多时候都是一个人从零到一进行开发或者接收项目能有好同事👋手把手教导,能大概了解整个项目的运行过程,直到我来到了一个用 AI 来生成业务的一个项目组里面,一切都发生了改变🌱。

我总结了单元测试的几点好处🔽:

  1. 能帮助接手项目的人快速了解项目的流程。

    这点真的很重要,我新接手项目的时候,就只有同事简单的说了几句话,我甚至只能知道这项目是 AI 提问回答流程,然后我直接懵逼,不过通过单元测试,我一步步看来下,倒是能大概了解了项目整体的逻辑。

  2. 降低代码出错的概率。

    每次在原有接口进行了一系列改动,在没有单元测试之前都要自己去接口文档手动尝试,甚至引来了测试一大堆指责。在使用单元测试之后,新增完的代码逻辑,直接新增对应功能的单元测试,直接全部执行,如果都能通过,这代码出问题的概率将会大大减少

  3. 不用担心影响数据库的数据。

    运行单元测试对于很多环境配置都可以直接使用独立的数据库,比如说 MySQL 的数据可以使用 H2 数据库,而 Redis 又可以使用 RedisServer 来创建。

单元测试的小技巧

对于单元测试,我总结了一些我自己使用中的小技巧,这些小技巧的使用往往能有奇效!

在这里插入图片描述

抽象测试类

@SpringBootTest(
        classes = { Application.class, },
        webEnvironment = SpringBootTest.WebEnvironment.MOCK,
        properties = {"spring.profiles.active=test"}
)
@Slf4j
@AutoConfigureMockMvc
public abstract class TestBase {protected static final Long TEST_GROUP_ID = 1L;@Autowired
    protected MockMvc mockMvc;}

这个测试类直接打上了需要使用的注解,后续使用直接继承即可,不用每次写上繁琐的注解,示例代码如下:

class Test extends TestBase {}

在 Spring 项目中使用 H2 代替 MySQL

  1. 引入 H2 依赖
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
  1. 通过 application-test.yml 来配置 H2 数据源
    spring:
      datasource:
        driver-class-name: org.h2.Driver
        schema: classpath:db/schema.sql #H2 数据库的建表语句
        data: classpath:db/data.sql #H2 数据库的插入数据语句
        url: jdbc:h2:mem:test #H2 数据库的默认连接地址
        username: test
        password: test
  1. 完成上面的步骤后,H2 数据库其实就已经替代掉 MySQL 了,但是要注意的是 MySQL 的 sql 语句与 H2 的有一丢丢的差别,语法可能并不适用,分享一个 IDEA 的插件就可以解决这个问题。

在这里插入图片描述

在单元测试中使用 Redis

有不少小伙伴总不喜欢在本地启动一个 Redis ,那么单元测试有什么解决办法呢!当然有!这就用到了 embedded-redis 的一个库,使用超级简单。

  1. 引入 embedded-redis 依赖
    <dependency>
        <groupId>it.ozimov</groupId>
        <artifactId>embedded-redis</artifactId>
        <version>0.7.3</version>
        <scope>test</scope>
        <!-- 不排除掉slf4j的话 会冲突-->
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-simple</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
  1. 直接在单元测试中编写
    private static RedisServer redisServer;@BeforeAll
    public static void beforeAll() {
        redisServer = RedisServer.builder().setting("maxheap 200m").port(6379).build();
        redisServer.start();
    }

Spring 单元测试 mock 数据

在我最近接收这个项目中调用 AI 花费是十分昂贵的,总不能单元每次都要调用 AI,不仅烧钱而且还有不确定性。有些需要 mock 的数据就可以使用 Mockito 这个强大的库来进行操作。

  1. 引入依赖(虽然说 SpringBoot 中会自带,但有时候我嫌弃他的版本不够高,但我又不能改 SpringBoot 依赖,就使用了覆盖)。
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-inline</artifactId>
        <version>3.12.4</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>3.12.4</version>
        <scope>test</scope>
    </dependency>
  1. mock 要代理的服务。

    举个例子我要 mock 一个类的方法,首先可以直接使用 @MockBean 注解来代理,这个注解跟 @Autowired 注解类似,也是让代理创建。接着就是让单元测试执行前,先将这个 Spring 代理对象 mock 创建它,给他指定返回的数据内容。示例代码如下:

    @MockBean
    private TestAgent testAgent;@BeforeEach
    public void beforeEach() {
        Mockito.when(testAgent.answer(any(), any())).thenAnswer(invocation -> {return "预期结果"});
    }

这里有几个注意的点:

1==> 这里的 any() 就是对应的输入任何数据,都要返回这个预期结果,其他的还可以自定义。
2==> 这里的代理只能返回一条数据或者里面自定义规则来返回不同数据,如果要每次都按顺序返回可以使用另一种方法 SideEffect 。
  1. 使用 SideEffect 来进行 mock 返回。

跟上面直接流程一样,但是不一样的是 thenAnswer 的后续处理,输入是一个 List 里面会按 List 内容的顺序依次返回。示例代码如下:

    List<String> list = new ArrayList();
    list.add("聪1");
    list.add("聪2");
    list.add("聪3");
    Mockito.when(testAgent.answer(Mockito.any(), Mockito.any())).thenAnswer(new SideEffect<>(list));

不想启动 Spring 容器

不想启动 Spring 容器,但是代码中用到了 Spring 的代理,SpringBoot 容器的启动十分的慢对于我的电脑,但是我要进行单元测试的部分其实并不涉及 Spring ,我直接进行 AI 请求访问而已,接着就可以使用我以下的方法,直接启动。

  1. 在单元测试中有移除 Spring 相关注解。

    移除掉注解后,在类上面打上 @ExtendWith(MockitoExtension.class) 注解,示例代码如下:

    @ExtendWith(MockitoExtension.class)
    class Test {
        ....
    }
  1. 对于交由 Spring 创建的对象进行手动创建。

    示例代码如下:

    // 不用使用注解
    private TestAgent testAgent;
    @BeforeEach
    void setUp() {
        testAgent = new TestAgent();
    }
  1. 后面直接使用对象直接请求即可。

最后

在这里插入图片描述

我想我大抵是疯了,我喜欢上了写单元测试,单元测试写完根本停不下来,再未来我会总结更多的单元测试小方法,如果你们有自己总结的一些关于单元测试的方法,欢迎大家一起分享学习~ 最后最后!我是聪希望可以跟大家一起学习,我的 Github:github.com/lhccong 如果里面有你感兴趣的项目不妨给我点个星星⭐和关注🔥,未来我还会持续写新的好玩的小项目。

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

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

相关文章

Unity | Shader基础知识(第十八集:Stencil应用-透视立方盒子)

目录 一、前言 二、场景布置 三、 shader部分 1.图片的部分 2.图片部分纯净代码 3.遮罩部分复习 4.深度写入 ZWrite 5.颜色遮罩ColorMask 6.遮罩纯净代码 四、场景中shader使用 五、作者的碎碎念 一、前言 因为这个内容稍微有点多&#xff0c;我尽力讲清楚了&#x…

VAE论文阅读

在网上看到的VAE解释&#xff0c;发现有两种版本&#xff1a; 按照原来论文中的公式纯数学推导&#xff0c;一般都是了解生成问题的人写的&#xff0c;对小白很不友好。按照实操版本的&#xff0c;非常简单易懂&#xff0c;比如苏神的。但是却忽略了论文中的公式推导&#xff…

jquery中pdf在页面的显示和导出

jquery中pdf在页面的显示和导出 01 显示pdf01 .pdf结尾在线接口显示到页面 &#xff08;pdf.js库怎么安装及使用&#xff09;&#xff1a;只显示一页02 如何用PDF.JS显示整个PDF (而不仅仅是一页)&#xff1f;03 jQuery实现在线预览PDF文件(通过a标签链接跳转)&#xff1a; 02 …

【网络安全】PostMessage:分析JS实现XSS

未经许可&#xff0c;不得转载。 文章目录 前言示例正文 前言 PostMessage是一个用于在网页间安全地发送消息的浏览器 API。它允许不同的窗口&#xff08;例如&#xff0c;来自同一域名下的不同页面或者不同域名下的跨域页面&#xff09;进行通信&#xff0c;而无需通过服务器…

【STM32 HAL库】全双工DMA双buffer的I2S使用

1、配置I2S 我们的有效数据是32位的&#xff0c;使用飞利浦格式。 2、配置DMA **这里需要注意&#xff1a;**i2s的DR寄存器是16位的&#xff0c;如果需要发送32位的数据&#xff0c;是需要写两次DR寄存器的&#xff0c;所以DMA的外设数据宽度设置16位&#xff0c;而不是32位。…

ArrayLis练习

代码呈现 import java.util.ArrayList;public class ArrayListTest {public static void main(String[] args) {//创建集合ArrayList<String> list new ArrayList();//添加元素list.add("A");list.add("B");list.add("C");list.add(&quo…

222.买卖股票的最佳时机(力扣)

代码解决 class Solution { public:int maxProfit(vector<int>& prices) {// 初始化最小买入价为第一个价格int min1 prices[0];// 初始化最大利润为0int max1 0;// 从第二天开始遍历价格数组for (int i 1; i < prices.size(); i) {// 计算当前价卖出的利润&a…

C++:智能指针shared_ptr、unique_ptr、weak_ptr的概念、用法即它们之间的关系

智能指针 (1)概述 A.Why&#xff08;C为什么引入智能指针&#xff09; C引入智能指针的根本原因就是解决手动管理动态内存所带来的问题&#xff0c;手动管理动态内存常见的问题如下&#xff1a;内存泄漏、悬挂指针、释放操作未定义等 内存泄漏问题&#xff1a; 当程序用光了它…

React的usestate设置了值后马上打印获取不到最新值

我们在使用usestate有时候设置了值后&#xff0c;我们想要更新一些值&#xff0c;这时候&#xff0c;我们要想要马上获取这个值去做一些处理&#xff0c;发现获取不到&#xff0c;这是为什么呢&#xff1f; 效果如下&#xff1a; 1、原因如下 在React中,当你使用useState钩子…

线程安全(七)ReentrantLock 简介、Condition 条件变量、锁的工作原理、synchronized 与 Lock 的区别

目录 一、ReentrantLock 简介1.1 Reentrant 的特性:1.2 基本语法1.3 ReentrantLock 的主要方法:1.4 lock()、tryLock()、lockInterruptibly() 的区别:二、Condition 条件变量2.1 什么是 Condition 条件变量?2.2 Condition 的核心方法:2.3 Condition 使用示例1:等待与唤醒…

PJA1介导的焦亡抑制是鼻咽癌产生耐药性的驱动因素

引用信息 文 章&#xff1a;PJA1-mediated suppression of pyroptosis as a driver of docetaxel resistance in nasopharyngeal carcinoma. 期 刊&#xff1a;Nature Communications&#xff08;影响因子&#xff1a;14.7&#xff09; 发表时间&#xff1a;2024年6月2…

LLaMA-Factory

文章目录 一、关于 LLaMA-Factory项目特色性能指标 二、如何使用1、安装 LLaMA Factory2、数据准备3、快速开始4、LLaMA Board 可视化微调5、构建 DockerCUDA 用户&#xff1a;昇腾 NPU 用户&#xff1a;不使用 Docker Compose 构建CUDA 用户&#xff1a;昇腾 NPU 用户&#xf…

变阻器与电位器有什么区别?

变阻器和电位器都是可以改变电阻值的电子元件&#xff0c;它们在电路中的作用和调节方式有一定的相似性&#xff0c;但它们之间还是存在一些区别的。 1. 结构上的区别&#xff1a;变阻器主要由固定电阻体和可动滑片组成&#xff0c;通过滑动滑片来改变电阻体的电阻值。而电位器…

数据库(创建数据库和表)

目录 一&#xff1a;创建数据库 二&#xff1a;创建表 2.1&#xff1a;创建employees表 2.2&#xff1a;创建orders表 2.3&#xff1a;创建invoices表 一&#xff1a;创建数据库 mysql> create database mydb6_product; Query OK, 1 row affected (0.01 sec) mysql&g…

linux centos limits.conf 修改错误,无法登陆问题修复 centos7.9

一、问题描述 由于修改/etc/security/limits.conf这个文件中的值不当&#xff0c;重启后会导致其账户无法远程登录&#xff0c;本机登录。 如改成这样《错误示范》&#xff1a; 会出现&#xff1a; 二、解决 现在知道是由于修改limits.conf文件不当造成的&#xff0c;那么就…

智慧农业新纪元:解锁新质生产力,加速产业数字化转型

粮食安全乃国家之根本&#xff0c;“浙江作为农业强省、粮食生产重要省份&#xff0c;在维护国家粮食安全大局中肩负着重大使命。浙江粮食产业经济年总产值已突破4800亿元&#xff0c;稳居全国前列&#xff0c;然而&#xff0c;同样面临着规模大而不强、质量效益有待提升、数字…

JVM高频面试点

文章目录 JVM内存模型程序计数器Java虚拟机栈本地方法栈Java堆方法区运行时常量池 Java对象对象的创建如何为对象分配内存 对象的内存布局对象头实例数据对齐填充 对象的访问定位 垃圾收集器找到垃圾引用计数法可达性分析&#xff08;根搜索法&#xff09; 引用概念的扩充回收方…

字符数组的魅力:C语言字符数组与字符串编程实践

1.概念 字符数组&#xff0c;数组元素是char(字符型)的数组&#xff0c;它可以是一维数组&#xff0c;也可以是二维数组。 2.定义的时候赋值 char ch1[]{c,h,i,n,a}; char ch2[]{"china"}; //相当于 char ch2[] "china"; 元素个数为6&#xff0c;默认会…

探索Linux世界 —— shell与权限的相关知识

一、shell以及其运行原理 1、什么是shell Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&#xff0c;也就是所谓的shell&#x…

6个高效再利用的UI作品集设计模板

UI 作品集是指用户界面设计师的个人作品集。它展示了设计师的设计能力、技巧和风格&#xff0c;也是充分展示他们设计能力的证明。优秀的UI 作品集应具有简洁明了、美观大方、良好的互动体验和明确的目标。本文将从两个方面的介绍 Ui 作品集模板的全部内容&#xff1a;UI 作品集…