单元测试总结

单元测试个人总结 单元测试-计划、设计、实现、执行;基本路径测试法;代码覆盖类型;代码覆盖率;需求覆盖率;桩代码;Mock代码;驱动代码;测试用例设计;白盒测试;黑盒测试 阅读详情

1.软件测试

软件测试是一种用来鉴定软件的正确性、完整性、安全性和质量的过程。主要包括单元测试、集成测试和功能测试等。

1.1 单元测试

主要由开发人员进行,确保程序单元符合预期。

1.2 集成测试

主要由开发人员进行,测试整体程序等功能和性能。

1.3 功能测试

主要由测试人员进行,测试程序是否符合预期。

2.单元测试内容

  1. 模块接口测试
  2. 模块局部数据结构测试
  3. 模块边界条件测试
  4. 模块中所有独立执行通路测试
  5. 模块的各条错误处理通路测试
  6. 模块的非法输入测试
  7. 代码重用测试
  8. 系统兼容测试

3.单元测试最佳实践

3.1 三到五步(Setup,输入,调用,输出,TearDown)

3.2 一致性(任何时候同样的输入需要同样的结果)

反例:

Date date = new Date();
Random.next();

3.3 原子性

所有的测试只有两种结果(成功或失败,不能部分测试通过)

3.4 单一职责

一个测试只验证一个行为

3.5 独立无耦合

  • 单元测试之间无相互调用(单元测试执行顺序无关)
  • 单元测试之间不能共享

3.6 隔离外部调用(不使用不依赖具体、真实的数据,例如:数据库、网络、外部文件等)

3.7 自描述(开发级文档)

3.8 单元测试逻辑

3.9 断言(包含具体的错误信息)

4.Mockito

单元测试开发中,我们经常会遇到测试的类有很多依赖的类、对象、资源,从而形成巨大的依赖树,mock可以模拟外部依赖,适应单元测试。

5.Mockito示例

模拟对象

// 模拟LinkedList 的一个对象  
LinkedList mockedList = mock(LinkedList.class);
// 此时调用get方法,会返回null,因为还没有对方法调用的返回值做模拟
System.out.println(mockedList.get(0)); 

模拟方法调用的返回值

// 模拟获取第一个元素时,返回字符串first。  给特定的方法调用返回固定值在官方说法中称为stub。
when(mockedList.get(0)).thenReturn("first");
// 此时打印输出first
System.out.println(mockedList.get(0)); 

模拟方法调用抛出异常

// 模拟获取第二个元素时,抛出RuntimeException  
when(mockedList.get(1)).thenThrow(new RuntimeException());
// 此时将会抛出RuntimeException  
System.out.println(mockedList.get(1));

如果一个函数没有返回值类型,那么可以使用此方法模拟异常抛出

doThrow(new RuntimeException("clear exception")).when(mockedList).clear();
mockedList.clear();

模拟调用方法时的参数匹配

// anyInt()匹配任何int参数,这意味着参数为任意值,其返回值均是element  
when(mockedList.get(anyInt())).thenReturn("element");
// 此时打印是element
System.out.println(mockedList.get(999));

模拟方法调用次数

// 调用add一次
mockedList.add("once"); 
// 下面两个写法验证效果一样,均验证add方法是否被调用了一次
verify(mockedList).add("once");
verify(mockedList, times(1)).add("once"); 

校验行为

// mock creation
 List mockedList = mock(List.class);
 // using mock object
 mockedList.add("one");
 mockedList.clear();
 //verification
 verify(mockedList).add("one");
 verify(mockedList).clear();

模拟方法调用(Stubbing)

//You can mock concrete classes, not just interfaces
 LinkedList mockedList = mock(LinkedList.class);
 //stubbing
 when(mockedList.get(0)).thenReturn("first");
 when(mockedList.get(1)).thenThrow(new RuntimeException());
 //following prints "first"
 System.out.println(mockedList.get(0));
 //following throws runtime exception
 System.out.println(mockedList.get(1));
 //following prints "null" because get(999) was not stubbed
 System.out.println(mockedList.get(999));
 verify(mockedList).get(0);

参数匹配

//stubbing using built-in anyInt() argument matcher
 when(mockedList.get(anyInt())).thenReturn("element");
 //stubbing using custom matcher (let's say isValid() returns your own matcher implementation):
 when(mockedList.contains(argThat(isValid()))).thenReturn("element");
 //following prints "element"
 System.out.println(mockedList.get(999));
 //you can also verify using an argument matcher
 verify(mockedList).get(anyInt());
 //argument matchers can also be written as Java 8 Lambdas
 verify(mockedList).add(someString -> someString.length() > 5);

校验方法调用次数

//using mock
 mockedList.add("once");

 mockedList.add("twice");
 mockedList.add("twice");

 mockedList.add("three times");
 mockedList.add("three times");
 mockedList.add("three times");
 //following two verifications work exactly the same - times(1) is used by default
 verify(mockedList).add("once");
 verify(mockedList, times(1)).add("once");
 //exact number of invocations verification
 verify(mockedList, times(2)).add("twice");
 verify(mockedList, times(3)).add("three times");
 //verification using never(). never() is an alias to times(0)
 verify(mockedList, never()).add("never happened");
 //verification using atLeast()/atMost()
 verify(mockedList, atLeastOnce()).add("three times");
 verify(mockedList, atLeast(2)).add("five times");
 verify(mockedList, atMost(5)).add("three times");

模拟无返回方法抛出异常

doThrow(new RuntimeException()).when(mockedList).clear();
//following throws RuntimeException:
mockedList.clear();

校验方法调用顺序

// A. Single mock whose methods must be invoked in a particular order
 List singleMock = mock(List.class);
 //using a single mock
 singleMock.add("was added first");
 singleMock.add("was added second");
 //create an inOrder verifier for a single mock
 InOrder inOrder = inOrder(singleMock);
 //following will make sure that add is first called with "was added first, then with "was added second"
 inOrder.verify(singleMock).add("was added first");
 inOrder.verify(singleMock).add("was added second");
// B. Multiple mocks that must be used in a particular order
 List firstMock = mock(List.class);
 List secondMock = mock(List.class);
 //using mocks
 firstMock.add("was called first");
 secondMock.add("was called second");
 //create inOrder object passing any mocks that need to be verified in order
 InOrder inOrder = inOrder(firstMock, secondMock);
 //following will make sure that firstMock was called before secondMock
 inOrder.verify(firstMock).add("was called first");
 inOrder.verify(secondMock).add("was called second");
 // Oh, and A + B can be mixed together at will

校验方法是否从未调用

//using mocks - only mockOne is interacted
 mockOne.add("one");
 //ordinary verification
 verify(mockOne).add("one");
 //verify that method was never called on a mock
 verify(mockOne, never()).add("two");
 //verify that other mocks were not interacted
 verifyZeroInteractions(mockTwo, mockThree);

快速创建Mock对象

public class ArticleManagerTest {
   @Mock private ArticleCalculator calculator;
      @Mock private ArticleDatabase database;
      @Mock private UserProvider userProvider;
      @Before
      public void before(){
          MockitoAnnotations.initMocks(this);
      }
}

自定义返回不同结果

when(mock.someMethod("some arg"))
   .thenThrow(new RuntimeException())  // 第一次会抛出异常
   .thenReturn("foo"); // 第二次会返回这个结果
//First call: throws runtime exception:
mock.someMethod("some arg"); // 第一次
//Second call: prints "foo"
System.out.println(mock.someMethod("some arg")); // 第二次
//Any consecutive call: prints "foo" as well (last stubbing wins).
System.out.println(mock.someMethod("some arg")); // 第n次(n> 2),依旧以最后返回最后一个配置

对返回结果进行拦截

when(mock.someMethod(anyString())).thenAnswer(new Answer() {
    Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        Object mock = invocation.getMock();
        return "called with arguments: " + args;
    }
});
//the following prints "called with arguments: foo"
System.out.println(mock.someMethod("foo"));

Mock函数操作

可以通过doThrow(), doAnswer(), doNothing(), doReturn() and doCallRealMethod() 来自定义函数操作。
暗中调用真实对象

List list = new LinkedList();
List spy = spy(list);
//optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);
//using the spy calls *real* methods
spy.add("one");
spy.add("two");
//prints "one" - the first element of a list
System.out.println(spy.get(0));
//size() method was stubbed - 100 is printed
System.out.println(spy.size());
//optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");

改变默认返回值

Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);
Foo mockTwo = mock(Foo.class, new YourOwnAnswer());

捕获函数的参数值

ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());

部分Mock

//you can create partial mock with spy() method:
List list = spy(new LinkedList());
//you can enable partial mock capabilities selectively on mocks:
Foo mock = mock(Foo.class);
//Be sure the real implementation is 'safe'.
//If real implementation throws exceptions or depends on specific state of the object then you're in trouble.
when(mock.someMethod()).thenCallRealMethod();

重置Mock

List mock = mock(List.class);
when(mock.size()).thenReturn(10);
mock.add(1);
reset(mock);
//at this point the mock forgot any interactions & stubbing

序列化

List<Object> list = new ArrayList<Object>();
List<Object> spy = mock(ArrayList.class, withSettings()
                 .spiedInstance(list)
                 .defaultAnswer(CALLS_REAL_METHODS)
                 .serializable());

检查超时

//passes when someMethod() is called within given time span
verify(mock, timeout(100)).someMethod();
//above is an alias to:
verify(mock, timeout(100).times(1)).someMethod();
//passes when som`eMethod() is called *exactly* 2 times within given time span
verify(mock, timeout(100).times(2)).someMethod();
//passes when someMethod() is called *at least* 2 times within given time span
verify(mock, timeout(100).atLeast(2)).someMethod();
//verifies someMethod() within given time span using given verification mode
//useful only if you have your own custom verification modes.
verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();

Mock详情

Mockito.mockingDetails(someObject).isMock();
Mockito.mockingDetails(someObject).isSpy();
什么是好的单元测试 - 单元测试的哲学 随着单元测试代码的日积月累,大量的 Thread.sleep 使测试速度越来越慢,单个本地测试也许还可以忍受,但全面自动化测试时乌龟一般的运行速度能让你抓狂。在测试代码在并发状态下的执行状况时,由于对测试结果的期待,或许会需要某些 Reduce 线程在 Map 线程之后才运行。另外请不要使用测试基类。调用对象的方法时尽可能的使用注入的对象,利用组合解决问题。在学习优秀的单元测试设计之前,了解一下糟糕的设计是快速掌握设计诀窍的“捷径”。学习完了上述测试的坏味道再加上适当的实践,就可以编写出合格的单元测试的。 阅读详情

相关推荐

你真的需要单元测试吗?

单元测试不是用来找Bug的 当你看到网上诸多关于单元测试的赞美时,仔细看看你就会发现很多说的其实是TDD(Test-Driven Development,测试驱动开发),不幸的是大多数人并没有注意区分这两个概念。在Writing Great Unit Tests: Best and Worst Practices中,Steven Sanderson强烈表达了自己的观点:Unit testing ...

戎码半生 4496

软件测试基础 - 单元测试理论部分

一、单元测试 1.定义:单元测试是对软件基本组成单元进行的测试,如函数(function或procedure)或一个类的方法(method)。 2.单元定义:单元具体有一些基本属性,如明确的功能、规格定义,明确的与其他部分的接口定义等,可清晰地与同一程序的其他单元划分。 在传统的结构化编程语言中,如C语言,进行测试的单元一般是函数或子过程;在面向对象的语言中,如C++,进...

weixin_30709929的博客 299

单元测试的总结

作为WEB开发人员在开发过程中总是需要测试各种请求  常规的方法则是启动WEB服务器 测试 出错 停掉WEB 改代码 重启WEB 测试  大量的时间都浪费在WEB服务器的启动上 今天给大家介绍一种不用启动WEB 直接采用单元测试的方法来测试请求是否准确  该方法基于SpringMVC 与 Spring Test 框架

超详细的单元测试总结

好的代码编写测试用例的时候是比较顺畅的,如果写单测的时候觉得目标代码很难测试,这时候大概率是目标代码编写不合理,需要优化重构下。新手对单测的框架没有意识,自己可能引用了一种, 其它框架 sdk 里面包含了另一种,比如 spring 的 framework 可能本身版本也五花八门,junit4 junit5 都有,使用的时候没注意乱用。测试有黑盒测试和白盒测试之分,黑盒测试顾名思义就是我们不了解盒子的内部结构,我们通过文档或者对该功能的理解,指定了相应的输入参数,然后判断得出的结果是否正确。

cs888zsy的博客 2635

单元测试报告模板

软件工程开发测试模板,包括单元测试方案,测试用例和测试总结模板

电机转矩、功率与转速:核心关系、公式推导与工程应用指南

在电气传动与自动化控制领域,理解旋转机械的核心物理量是进行设备选型、系统设计和故障诊断的基础。转矩、功率和转速构成了描述电机性能的“铁三角”,它们之间通过经典的物理公式紧密关联。从原理上讲,功率是单位时间内做功的能力,转矩是产生旋转运动的力矩,而转速则决定了运动快慢。这三者的关系(P = T × n / 9550)不仅是理论核心,更是工程实践中的关键计算工具,直接关系到电机的驱动能力、能耗与系统匹配。其技术价值在于,它为从微型伺服电机到大型工业传动系统的设计提供了统一的量化分析框架。在应用场景上,无论是为输

weixin_29184371的博客 258

Java单元测试

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。“单元”可以是一个函数、方法、类、功能模块或者子系统。单元测试的核心在于行、分支覆盖率,不关注业务正确性。

yyp0719的博客 7951

小爱音箱Play增强版刷机接入大模型:自定义唤醒词与远程控制全攻略

智能音箱作为家庭语音入口,受限于厂商预设技能,难以满足个性化需求。通过串口刷机与Linux系统分区改造,可以完全掌控设备底层,将豆包、通义千问等大模型API接入原有音频链路,实现真正智能的语音问答。自定义唤醒词打破了“小爱同学”的唯一唤醒方式,结合ESP32-S3外挂模块,还能优化远场拾音。更深入的应用在于将音箱打造为家庭中控,通过大模型工具调用解析自然语言指令,实现远程控制电脑、智能灯等设备。本文从设备选型、拆机串口、系统备份到语音链路搭建,完整梳理了小爱音箱Play增强版的改造路径,适合具备动手能力的开

weixin_30036289的博客 716

单元测试详解

维基百科中是这样描述的:在计算机编程中,单元测试又称为模块测试,是针对程序模块来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类、抽象类、或者派生类中的方法。

Edward_hjh的博客 1万+

解密m3u8视频合并:从猫抓插件到本地文件修改全流程

本文详细解析了m3u8视频合并的全流程,特别针对加密视频片段提供了解决方案。从使用猫抓插件捕获m3u8文件地址,到利用N_m3u8DL-CLI工具自动下载、解密并合并ts片段,手把手教你处理AES-128加密等常见问题,最终生成完整的本地MP4文件,适合需要备份或处理流媒体资源的用户。

weixin_29290947的博客 1360

【硬件】通俗易懂的讲解晶体管(三极管和MOS管)的工作原理

晶体管是一个简单的元器件,可用于构建许多有趣的项目。在本文中,我将用通俗易懂的语言给您讲解晶体管的工作原理,以便您可以在电路设计中更好的使用静态管。一旦你学习这些基础知识,对以后的设计和使用来说,将会变得非常容易。我们将重点介绍两种最常见的晶体管:双极型晶体管(三极管)和MOSFET。晶体管的工作原理其实是类似于电子开关。它可以打开和关闭电路。一个简单的思考方法是将晶体管视为无源的继电器。晶体管类似于继电器,从某种意义上说,您可以使用它来打开和关闭某些东西。但晶体管也可以部分导通,一般在放大电路中使用,这部

1万+

什么是单元测试?如何做好单元测试?

在正式开始今天的话题之前,我先给你分享一个工厂生产电视机的例子。 工厂首先会将各种电子元器件按照图纸组装在一起构成各个功能电路板,比如供电板、音视频解码板、射频接收板等,然后再将这些电路板组装起来构成一个完整的电视机。 如果一切顺利,接通电源后,你就可以开始观看电视节目了。但是很不幸,大多数情况下组装完成的电视机根本无法开机,这时你就需要把电视机拆开,然后逐个模块排查问题。 假设你发现是供电...

chen__an的博客 6973

Halcon实战:5种边缘检测算子对比(Sobel、Roberts、Prewitt、Kirsch、Canny)

本文深入对比了Halcon中Sobel、Roberts、Prewitt、Kirsch和Canny五大边缘检测算子的实战表现与核心差异。通过工业图像实例与代码解析,提供了基于噪声水平、边缘连续性及实时性要求的场景化选型指南,帮助工程师精准选择最适合的算子以优化视觉检测流程。

weixin_29266007的博客 392

如何做单元测试

如何做好单元测试一. 定义二. 为什么要做单元测试三. 单元测试用例四. 阿里单元测试规约五. 测试框架的使用Junit(下面以Junit4 为例来介绍)1.1、什么是Junit1.2、为何使用Junit1.3、Junit的快速入门导入Junit对应jar包(maven):下面我们来写一段简单的逻辑代码进行单元测试演练1.4、Junit测试失败的两种情况:测试失败的情况一测试失败情况二:1.5、Junit的运行流程:1.6、Junit的常用注解:1.7、Junit的参数设置1.8、Junit模拟方法异常执行

Github: https://github.com/jcxzzy 掘金:https://juejin.cn/user/879249395028558 5875

【HAL库】STM32CubeMX开发----STM32F407----ETH+LAN8720A+LWIP----ping通

本次实验以芯片为MCU,使用25MHz外部时钟源。以太网PHY层芯片为LAN8720A,由MCU引脚PA8提供时钟。

MQ0522的博客 4843

ArcGIS笔记2_如何将经纬度WGS84地理坐标系转换为米单位CGCS2000投影坐标系

本博文则主要讲解,如果我们手里拿到的shp文件是在ArcGIS中,如何将经纬度WGS84地理坐标系转换为米单位CGCS2000投影坐标系。

晏长街的博客 4万+

【C++ 单元测试】单元测试的意义与实战要领

在软件开发的漫长历程中,测试始终扮演着不可或缺的角色。单元测试(Unit Test)则是其中最基础、也是最关键的部分,它让开发者能够在最小功能单元上进行验证。就像心理学家马斯洛所言「人类行为往往源于对安全感的需求」,单元测试就是开发者建立安全感的重要手段,通过快速、频繁、可控的验证,确保每个功能单元都能可靠运行。

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 1914

蓝桥杯第七届省赛试题--“模拟风扇控制系统”

题目要求 功能简述 “模拟风扇控制系统”能够模拟电风扇工作,通过按键控制风扇的转动速度和定时时间,数码管实时显示风扇的工作模式,动态倒计时显示剩余的定时时间,系统主要由数码管显示、单片机最小系统、按键输入和电机控制保护电路组成,系统框图如图 1 所示: 单总线驱动程序、CT107D 单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。程序流程图及相关工程文件请以考生...

qq_43280087的博客 2659

什么是单元测试,如何去写一个单元测试

但一些场景下,如果项目中没有使用BFF承担数据处理的角色,后端也没能提供完全符合前端数据结构需求的接口时,不可避免的,开发人员需要在此处完善数据处理的逻辑,以便获取清洗或聚合后的数据,因而这种情况下,UT覆盖是非常有必要的。表达力强的测试,能在失败的时候给你非常迅速的反馈,看到测试时,你就知道它测的业务点是啥 测试挂掉时,能清楚地知道失败的业务场景、期望数据与实际输出的差异,跟写声明式的代码一样的道理,测试需要都是简单的声明:准备数据、调用函数、断言,让人一眼就明白这个测试在测什么。

2401_85696278的博客 1795

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

【单元测试】单元测试介绍

一般来说,做单元测试均采用的是商用的测试工具或自行开发的测试工具,用例的编写都是在测试工具上完成,测试用例都是一些测试脚本,都以文件的方式来保存,故其用例的执行过程主要是由测试工具根据所编写的具体的测试用例脚本来完成,这样对于用例的管理和执行也非常灵活。千万不要误解测试覆盖,测试覆盖并不是我们最求的目的,它只是评价测试的一种方式,为测试提供指导和依据。测试用例的优化主要是指用例的合并、修改和删除,减少冗余的无价值的测试,其优化依据来源于测试后的测试数据分析和评估,其中测试覆盖也是用例优化的主要参考。

加油站发光博主 3156

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

单元测试

一、什么是单元测试? 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。 二、单元测试的好处? 1)减少bug 一个机器,由各种细小的零件组成,如果其中某件零件坏了,机器运行故障。必须保证每个零件都按设计图要求的规格,机器才能正常运行。 一个可单元测试...

bobolan 1万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

单元测试整理(一)——单元测试是什么,有什么好处

单元测试是什么 单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确,通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为1。 单元测试的好处 1,单元测试不但会使你的工作完成得更轻松。而且会令你的设计会变得更好,甚至大大减少你花在调试上面的时间 2,提高代码质量 3,减少bug,快速定位bug 4,放心地修改、重构 5,显

potatostyles的博客 3万+

提高单元测试的意义&如何用Mockito做好单元测试

​ 定义:单元测试是开发者编写的一小段代码,用于检验代码的一个很小的,很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件下特定函数的行为(《单元测试之道 Java版》)。换句话说,指对软件中的最小可测试单元进行检查和验证,针对的是类和方法。我们是否需要从头开始一行行代码写?不用的,有些插件可以帮忙生成部分代码生成代码的插件idea自带的生成功能TestMe插件,这款插件只会给你生成一个壳,真正逻辑需要自己编写。squaretest插件,这里就不展开讲了。

qq_43663493的博客 2452
上一篇: Spring Cloud Config 使用本地配置文件
下一篇: Spring StateMachine
sunbufu
博客等级 码龄11年 17粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值