单元测试的心法分享

大家好,我是G探险者!

今天我们简单聊聊单元测试的哪些事儿~

两天时间我玩明白了单元测试的套路。

这里我分享一下思路。

在我眼里单元测试室什么?

请看这张草图:

单元测试主要关注单个代码单元(通常是类或方法)的逻辑正确性,而不是功能测试的全面性。具体来说:

单元测试的目的

  1. 验证逻辑路径:单元测试旨在验证代码逻辑中的不同路径是否按预期执行。这包括条件分支(如if-else语句)、循环、异常处理等。
  2. 隔离测试:通过mock或stub来隔离被测试的单元,使其不依赖外部资源(如数据库、网络服务)或其他复杂对象。
  3. 快速反馈:单元测试应该快速执行,提供即时的反馈,帮助开发者在早期发现并修复问题。
  4. 保证代码质量:通过覆盖不同的逻辑路径和边界情况,确保代码在各种情况下都能正确运行。

与功能测试的区别

  • 单元测试:专注于验证单个代码单元的内部逻辑,不要求模拟复杂的实际场景。变量值的准确性不是重点,重点是逻辑是否按预期执行。
  • 功能测试:验证整个系统或子系统的功能是否满足需求,通常在集成环境中进行,涉及实际的外部资源和复杂的交互。

单元测试中的Mock实践

  1. 分析需要mock的对象和行为

    • 确定哪些外部依赖(如数据库、网络服务)需要被mock。
    • 只mock那些必要的对象,保持测试的简洁性。
  2. 创建mock对象的方式

    • 使用@Mock注解或Mockito.mock()方法创建mock对象。
    • 可以使用@RunWith(MockitoJUnitRunner.class)MockitoAnnotations.initMocks(this)来初始化@Mock注解的字段。
  3. mock的目的

    • 隔离被测试单元,确保测试专注于目标代码逻辑。
    • 控制依赖对象的行为和状态,模拟各种异常和边界条件,验证代码的健壮性和正确性。
  4. mock对象和行为

    • 使用when().thenReturn()模拟方法返回特定值。
    • 使用when().thenThrow()模拟方法抛出异常。
    • 使用thenReturn()多次或thenAnswer()模拟连续调用时的不同结果。
    • 使用verify()方法验证方法的调用次数和顺序,确保逻辑执行的正确性。

这里我总结了一些些单元测试基本套路吧,整理一个模板。

分析方法

假设我们有一个类 MyClass 和其中的一个方法 myMethod。在分析该方法时,你需要考虑以下几个方面:

  1. 输入参数:方法接受哪些参数?
  2. 依赖对象:方法中使用了哪些类的实例?
  3. 行为动作:方法内部调用了哪些其他方法?是否有外部依赖,如数据库、网络调用等?
  4. 输出结果:方法返回什么?是否有副作用(如修改了类的状态、写入日志等)?

分析示例

假设 MyClass 的 myMethod 如下:

public class MyClass {
    private MyDependency dependency;

    public MyClass(MyDependency dependency) {
        this.dependency = dependency;
    }

    public String myMethod(String input) {
        String transformedInput = input.toUpperCase();
        boolean isValid = dependency.validate(transformedInput);
        if (isValid) {
            return "Valid: " + transformedInput;
        } else {
            return "Invalid: " + transformedInput;
        }
    }
}

分析步骤

  1. 输入参数input(字符串)
  2. 依赖对象MyDependency(通过构造函数注入)
  3. 行为动作:调用了 dependency.validate(transformedInput)
  4. 输出结果:返回一个字符串,形式为 "Valid: " + transformedInput 或 "Invalid: " + transformedInput

单元测试模板

import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(MockitoJUnitRunner.class)
public class MyClassTest {

    @Mock
    private MyDependency mockDependency;

    @InjectMocks
    private MyClass myClass;

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

    @Test
    public void testMyMethod_ValidInput() {
        // Arrange
        String input = "test";
        String transformedInput = "TEST";
        when(mockDependency.validate(transformedInput)).thenReturn(true);

        // Act
        String result = myClass.myMethod(input);

        // Assert
        assertEquals("Valid: TEST", result);
        verify(mockDependency).validate(transformedInput);
    }

    @Test
    public void testMyMethod_InvalidInput() {
        // Arrange
        String input = "test";
        String transformedInput = "TEST";
        when(mockDependency.validate(transformedInput)).thenReturn(false);

        // Act
        String result = myClass.myMethod(input);

        // Assert
        assertEquals("Invalid: TEST", result);
        verify(mockDependency).validate(transformedInput);
    }
}

模板解析

  1. 导入依赖:导入了Mockito和JUnit的静态方法。
  2. 测试类定义:定义了 MyClassTest 测试类。
  3. Mock对象:使用 @Mock 注解创建 MyDependency 的mock对象。
  4. 测试准备:在 setUp 方法中初始化mock对象,并创建 MyClass 实例。
  5. 测试方法:定义两个测试方法,分别测试myMethod 在 validate 方法返回 true 和 false 的情况下的行为。

注意事项

  • 测试覆盖:确保测试覆盖了所有可能的输入和边界情况。
  • 行为验证:使用 verify 方法验证依赖对象的方法调用情况。
  • 异常处理:如果方法可能抛出异常,编写相应的测试用例。

通过这个模板,你可以系统地分析并编写单元测试,确保测试的全面性和准确性。

题外话

当然现在idea 里面有相关的些单元测试的插件,比如Squaretest,或者你直接通过ChatGPT来写。但是你得知道原理。

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

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

相关文章

云原生架构案例分析_2.云原生技术助力某汽车公司数字化转型实践

名词解释: 互联网 在“互联网”模式下,我们仅仅把互联网看作是一种传播工具、传播手段、传播渠道和传播平台,对于互联网的应用大体上是在既有的运作逻辑的基础之上,把互联网作为延伸传媒影响力、价值和功能的一种延伸型工具&…

秒杀基本功能开发(不考虑高并发情况)

文章目录 1.显示秒杀状态1.controller修改GoodsController.java的toDetail方法,响应秒杀状态和秒杀剩余时间 2.前端1.goodsDetail.html 图片下面添加一行秒杀开始时间2.goodsDetail.html 添加计时器js代码 3.测试1.秒杀进行中2.修改db的秒杀开始时间为明天3.出现秒杀…

msvcr120.dll是干嘛的?出现找不到msvcr120.dll丢失怎样解决

msvcr120.dll是Microsoft Visual C 2012 Redistributable的核心文件,它是Microsoft Corporation开发的C/C运行时库文件之一。这个文件通常与应用程序一起安装,为应用程序提供许多基本的运行时功能,包括内存管理、异常处理、输入/输出操作等。…

Jenkins、GitLab部署项目

1、安装JDK 1.1、下载openJdk11 yum -y install fontconfig java-11-openjdk1.2、查看安装的版本号 java -version1.3、配置环境变量 vim /etc/profile在最底部添加即可 export JAVA_HOME/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64 export PATH$JAVA_HOME/…

SpringBoot注解--10--@Bean,对象注入的三种方法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 Bean一、如何使用方法注解注意Bean 的命名规则,当没有设置 name 属性时,那么 bean 默认的名称就是方法名,当设置了 name 属性之后…

【OJ】C++ | 二叉树进阶 · 合集(2)

摘要:根据二叉树创建字符串、二叉树的最近公共祖先、二叉树的层序遍历 前言:承接上文,本文继续提供二叉树进阶有关题目的解法。如有错误,烦请指正。 目录 1. 根据二叉树创建字符串 题解及代码 2. 二叉树的最近公共祖先 题解及…

PHAR反序列化

PHAR PHAR(PHP Archive)文件是一种归档文件格式,phar文件本质上是一种压缩文件,会以序列化的形式存储用户自定义的meta-data。当受影响的文件操作函数调用phar文件时,会自动反序列化meta-data内的内容,这里就是我们反序…

2024年06月编程语言流行度排名

点击查看最新编程语言流行度排名(每月更新) 2024年06月编程语言流行度排名 编程语言流行度排名是通过分析在谷歌上搜索语言教程的频率而创建的 一门语言教程被搜索的次数越多,大家就会认为该语言越受欢迎。这是一个领先指标。原始数据来自…

JAVA和爬虫,那个值得学习

如果你是初学者,建议先从基础的编程语言学起,比如Java,它能为你打下坚实的编程基础,并且在未来转学其他语言或技术时更加容易。随着编程基础的建立,你可以根据自己的兴趣或职业规划,学习爬虫技术作为补充技…

使用python下载股票数据至sqlite数据库

代码下载地址: https://download.csdn.net/download/weixin_44600457/89389489

961题库 北航计算机 计算机网络 附答案 选择题形式

有题目和答案,没有解析,不懂的题问大模型即可,无偿分享。 第1组 习题 OSI 参考模型的第 5 层( 自下而上 ) 完成的主要功能是 A. 差错控制 B. 路由选择 C. 会话管理 D. 数据表示转换 100BaseT 快速以太网使用的导向传输介质是 A. 双绞线 B. …

德人合科技——@天锐绿盾 | -文档透明加密系统

天锐绿盾文档透明加密系统是一种先进的数据安全解决方案,旨在保护企业和组织的敏感信息,防止未经授权的访问和泄漏。 PC地址: https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 以下是该系统的一些关键特点和功…

FJSP:常春藤算法(Ivy algorithm,LVYA)求解柔性作业车间调度问题(FJSP),提供MATLAB代码

详细介绍 FJSP:常春藤算法(Ivy algorithm,LVYA)求解柔性作业车间调度问题(FJSP),提供MATLAB代码-CSDN博客 完整MATLAB代码 FJSP:常春藤算法(Ivy algorithm,…

随后记: uniapp uview u-dropdown 下拉菜单固定高度滑动不生效

使用u-dropdown 下拉组件 按照uview官网讲解使用 配置根本不生效 scroll-y"true" style"height: 200rpx;" 但是在下拉的时候,不能上下滑动 ,原因是自带的遮罩层挡住了 解决办法:在下拉菜单打开和关闭的时候&#xff0c…

英语四级翻译练习笔记②——大学英语四级考试2023年12月真题(第二套)

目录 引言(必看) 四级翻译评分标准分析及真题解析 四级翻译评分标准 四级翻译真题 学生作答 错误标注 标准满分答案 提高翻译水平的建议 引言(必看) 这是一篇英语四级翻译的练习的专栏,如果相信我的话就将这…

树莓派5烧系统和ssh远程实现

1、硬件说明 树莓派5 64G micro SD卡读卡器 2、烧录系统过程记录 之前写过一篇pi4B烧录Ubuntu22.04的博客,这篇就简单记录备份下 2.1 去ubuntu官网在树莓派上安装Ubuntu | Ubuntu下载Ubuntu 桌面 24.04 LTS 我之前已经下好了就有个(1) 2.2 用读卡器把SD卡插到…

车辆前向碰撞预警系统性能要求和测试规程

前言 本文整理《GB/T 33577-2017 智能运输系统-车辆前向碰撞预警系统性能要求和测试规程》国标文件关键信息,FCW系统性能和测试右给深层次的认识。 术语和定义 车辆前向碰撞预警系统 forward vehicle collision warning system自车 subject vehicle(SV)目标车辆 target ve…

Lagrange ZK Coprocessor:革新区块链领域的大数据应用

1. 引言 2024年5月11日,Lagrange Labs宣称获得由Founders Fund领投(Archetype Ventures, 1kx, Maven11, Fenbushi Capital, Volt Capital, CMT Digital, Mantle Ecosystem Fund和其它天使投资人跟头)的1320万美金种子轮融资,致力于…

【spring】第一篇 IOC和DI入门案例

Spring到底是如何来实现IOC和DI的,那接下来就通过一些简单的入门案例,来演示下具体实现过程。 目录 前期准备 一、IOC入门案例 思路分析 代码实现 二、DI入门案例 思路分析 代码实现 总结 前期准备 使用IDEA创建Maven项目,首先需要配…

linux进阶的一些操作以及知识点------习题集(实践)

请创建以你姓名全拼的用户luwenhua,将其设置为免密登录,切换到luwenhua用户,打开终端,完成以下操作 (一)bash脚本基础练习 1)第一题:请在终端里定义两个用户变量num120&#xff0c…