单元测试的最佳实践

整体架构

891538a3dc589da6d123e79d1f3448a7.jpeg

合适的架构可以提升可测试性。比如菱形对称架构的模块化和解耦特性使得系统各个部分可以独立进行单元测试。这不仅提高了测试的效率,还能够减少测试的依赖性,提高测试准确性。

代码设计

代码设计和可测试性有密切关联。强烈建议一个方法的代码行数不要太多。这样,如果需要细粒度单元测试(需要比较高的代码覆盖率的单元测试),就更容易。大不了把私有方法变成公有,加一

@VisibleForTesting注解来测试。

其他设计比如采用易于测试的设计模式:‌选择合适的设计模式可以显著提高代码的可测试性。‌例如,‌使用依赖注入(‌DI)‌模式可以使依赖关系在运行时动态绑定,‌便于模拟和替换依赖项,‌从而更容易进行单元测试。‌

测试框架

分布式微服务系统而言,“粗粒度单元测试”最大挑战在于如何解决周边依赖问题,对于一个典型的应用而言,它可能会依赖数据库、消息中间件、缓存系统等,以及周边的其它服务。如何处理这些依赖,是我们必须要面对和要解决的问题。

其实解决方案只有一种叫Test Double(测试替身),即要用“替身”来代替依赖,从而让程序在没有真正依赖环境的情况下,仍然可以运行,验证功能。这些“替身”有不少fancy的名字,比如dummy、fake、stub、mock、spy等,这里我就不啰嗦这些概念的差异了,也不重要。重要的是我们该如何高效的实施“粗粒度单元测试”。

Mock做替身

使用mock做“替身”是我们处理外部依赖的最常见做法,有很多的框架比如Mockito,EasyMock支持我们去做mock的事情。

这种方法有效,但存在两个问题:

比较繁琐,当需要构造的对象有大量字段的时候,需要额外写很多的代码。

有些功能测不全,比如这里的SQL语句就不能被测试到,因为数据库的访问是被mock掉的。

Embedded Server做替身

鉴于以上的问题,我发现很多团队都开始转向embedded方案,即在本地拉起一个真实的内嵌依赖服务,作为依赖的“替身”。比如我用到了Redis缓存,那么我可以使用embedded-redis启动一个本地的redis,从而连接到“真实”的redis环境。使用很简单,只需要加入下面的依赖就可以。在Junit5的Extension帮助下,我们可以很优雅的使用embedded的服务。

<dependency><groupId>com.github.codemonstur</groupId><artifactId>embedded-redis</artifactId><version>1.4.2</version><scope>test</scope>
</dependency>

类似的,我们常用的中间件比如kafka、MySQL、MongoDB等等都有相对应的embedded的方案。对于非中间件,比如其它服务依赖,我们可以使用wiremock来做其它服务API的“替身”。这些动作在很大程度上可以帮助我们消解依赖问题,这样做可以给我们带来以下好处:

在同样代码覆盖率的情况下,使用embedded的集成测试方案,可以写更少的测试用例和代码,研发效率更高

因为使用的是真实中间件服务,可以让我们的测试更加贴近真实环境,测试的有效性更高。

测试的入口是接口。这种更大测试粒度带来的好处是,可以帮助我们更好的重构内部业务逻辑,而不用担心破坏测试用例,如果UT太细的话,重构代码的同时还要重写UT,比较麻烦。

你也许会说,和Mock方案相比,这里的数据准备并没有比Mock少多少啊,实际上的确如此,对于测试数据,我们可以使用测试夹具(Test Fixtures)把测试数据用json/xml的形式放在resource下面,这样可以提升我们的数据复用和数据准备效率。

除此之外,embedded方案还引入了一个比较严重的问题——慢!即在运行测试的时候,需要拉起整个环境,整个过程很耗时,一般情况下,如果要启动3个embedded服务,短则一分钟多则几分钟,这显然与我们所期望的单测要“短平快”不相符。“慢”会极大的抑制我们运行UT的积极性,也就不能享受UT带来的quick feedback好处,更不用说TDD了。

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

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

相关文章

Android 15 适配整理——实践版

背景 谷歌发布Android 15后&#xff0c;国内的手机厂商迅速行动&#xff0c;开始了新系统的适配工作。小米、OPPO、vivo和联想等金标联盟成员联合发布了适配公告&#xff0c;督促APP开发者在2024年8月31日前完成适配工作&#xff0c;否则将面临搜索标签提示、应用降级、分机型…

JavaWeb笔记_JSTL标签库JavaEE三层架构案例

一.JSTL标签库 1.1 JSTL概述 JSTL(jsp standard tag library):JSP标准标签库,它是针对EL表达式一个扩展,通过JSTL标签库与EL表达式结合可以完成更强大的功能 JSTL它是一种标签语言,JSTL不是JSP内置标签 JSTL标签库主要包含: ****核心标签 格式化标签 …

Android平台轻量级RTSP服务模块二次封装版调用说明

技术背景 在前面的blog&#xff0c;我们发布了Android平台轻量级RTSP服务模块的技术对接说明&#xff0c;好多开发者希望&#xff0c;更黑盒的对接轻量级RTSP服务这块&#xff0c;专注于自身业务逻辑。为此&#xff0c;我们针对Android平台轻量级RTSP服务模块&#xff0c;做了…

解析capl文件生成XML Test Module对应的xml工具

之前一直用的CAPL Test Module来写代码&#xff0c;所有的控制都是在MainTest()函数来实现的&#xff0c;但是有一次&#xff0c;代码都写完了&#xff0c;突然需要用xml的这种方式来实现&#xff0c;很突然&#xff0c;之前也没研究过&#xff0c;整理这个xml整的一身汗&#…

vue3前端开发-小兔鲜项目-登录组件的开发表单验证

vue3前端开发-小兔鲜项目-登录组件的开发表单验证&#xff01;现在开始写登录页面的内容。首先这一次完成基础的首页按钮点击跳转&#xff0c;以及初始化一些简单的表单的输入验证。后期还会继续完善内容。 1&#xff1a;首先还是准备好login页面的组件代码内容。 <script …

企业风险管理的智能监控:Kompas.ai如何预警潜在风险

在企业运营中&#xff0c;风险管理是确保业务连续性和稳健发展的关键环节。随着技术的进步&#xff0c;智能风险管理成为预防损失和识别潜在风险的重要手段。Kompas.ai&#xff0c;作为一款先进的智能监控工具&#xff0c;正通过数据分析和模式识别技术&#xff0c;帮助企业实现…

《华为数据之道》读书笔记六---面向自助消费的数据服务建设

七、从结果管理到过程管理&#xff0c; 从能“看”到能“管” 1、数据赋能业务运营 数字化运营旨在利用数字化技术获取、管理和分析数据&#xff0c;从而为企业的战略决策与业务运营提供可量化的、科学的支撑。 数字化运营归根结底是运营&#xff0c;旨在推动运营效率与能力的…

基站光伏直流叠光能效管理方案

安科瑞 华楠 基站现状和趋势 5G基站是专门提供5G网络服务的公用移动通信基站。5G基站主要用于提供5G空口协议功能&#xff0c;支持与用户设备、核心网之间的通信。按照逻辑功能划分&#xff0c;5G基站可分为5G基带单元与5G射频单元&#xff0c;二者之间可通过CPRI或eCPRI接口…

AFSim仿真系统-架构概览

引言 本文档从最终用户的角度描述了AFSIM架构&#xff0c;旨在帮助最终用户深入了解AFSIM的操作概念。 核心架构 AFSIM基于面向对象的C架构&#xff0c;提供了一种可扩展和模块化的架构&#xff0c;使得许多附加功能能够轻松集成。AFSIM允许新的组件模型&#xff08;如传感器、…

vue3.0学习笔记(二)——生命周期与响应式数据(ref,reactive,toRef,toRefs函数)

1. 组合API-setup函数 使用细节&#xff1a; setup 是一个新的组件选项&#xff0c;作为组件中使用组合API的起点。从组件生命周期来看&#xff0c;它的执行在组件实例创建之前vue2.x的beforeCreate执行。这就意味着在setup函数中 this 还不是组件实例&#xff0c;this 此时是…

SpringBoot 实现图形验证码

一、最终结果展示 二、前端代码 2.1 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"utf-8"><title>验证码</title><style>#inputCaptcha {height: 30px;vertical-align: middle;}#verifica…

交易积累-BR

BR指标&#xff0c;全称是“买卖意愿比率”&#xff08;Bull/Bear Ratio&#xff09;&#xff0c;是一个衡量市场买卖力量对比的技术分析工具。BR指标是由中国的技术分析师发展起来的&#xff0c;它通过比较股票或市场在一定时间内的上涨能量与下跌能量来评估市场情绪和潜在的趋…

自动驾驶(八十八)---------通讯之SOMEIP

1. 什么是SOME/IP 服务导向架构&#xff08;SOA&#xff0c;Service-Oriented Architecture&#xff09;是一种设计软件系统的方法&#xff0c;强调通过可重用的服务来实现系统的松散耦合。每个服务是独立的功能单元&#xff0c;可以被不同的应用程序使用。这些服务通过标准化的…

【教程】Node.js+Apache 部署网页全过程(非常详细!)

文章目录 背景0. 前置假设1. 更新系统和安装必要软件2. 打包并上传项目到服务器2.1 识别需要上传的文件2.2 文件归档和压缩2.3 压缩文件上传到服务器2.4 解压文件 3. 配置Node.js应用3.1 启动 PM23.2 确认 PM2 进程 4. 配置Apache反向代理5. 启用必要的Apache模块6. 检查 Apach…

linux如何卸载python3.5

卸载&#xff1a; 1、卸载python3.5 sudo apt-get remove python3.5 2、卸载python3.5及其依赖 sudo apt-get remove --auto-remove python3.5 3、清除python3.5 sudo apt-get purge python3.5 或者 sudo apt-get purge --auto-remove python3.5

AI发展下的伦理挑战:构建未来科技的道德框架

一、引言 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;我们正处在一个前所未有的科技变革时代。AI不仅在医疗、教育、金融、交通等领域展现出巨大的应用潜力&#xff0c;也在日常生活中扮演着越来越重要的角色。然而&#xff0c;这一技术的迅猛进步也带来…

【OpenCV C++20 学习笔记】操作图片

操作图片 概述图片的导入和保存对导入的图片的操作获取像素值Point类型和图片像素 内存管理和引用计数一些简便操作图片可视化更精确的类型转换 概述 在本专栏的第一篇文章中就介绍了一个用OpenCV处理图片的实例&#xff08;《图片处理基础》&#xff09;&#xff0c;这篇文章…

【Linux】信号3——信号的处理

1.信号的处理 我们都说信号被收到了&#xff0c;可能不会里面处理 信号是什么时候被处理的呢&#xff1f; 前提是我们得知道自己收到了信号&#xff0c;进程就得在合适的时候去查自己的pending表和block表&#xff0c;这些属于内核数据结构&#xff0c;进程一定要处于内核态&a…

学习测试12-车(略)

系统讲解&#xff0c;可以在懂车帝网站去了解汽车结构

DMv8共享存储集群部署

DMv8共享存储集群部署 环境说明 操作系统&#xff1a;centos7.6 服务器&#xff1a;2台虚拟机 达梦数据库版本&#xff1a;达梦V8 安装前准备工作 参考达梦官方文档&#xff1a;https://eco.dameng.com/document/dm/zh-cn/ops/DSC-installation-cluster.html#%E4%B8%80%E3…