单元测试的学习心得

1.什么是单元测试?

在计算机编程中,单元测试1(Unit Testing)又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确检验的测试工作。对于面向对象编程,最小单元就是方法,包括基类、抽象类、派生类中的方法。

通常来说,每修改一次代码就要进行最少一次单元测试,在编写过程中可能要进行多次单元测试,以证实程序达到软件规格书要求的工作目标,没有程序错误。
每个理想的测试案例独立于其它案例;为测试时隔离模块,经常使用stubs、mock、fake等测试马甲程序。单元测试经常有开发者编写,用于确保他们所写的代码匹配软件需求和遵循开发需求。它的实施方式可以是非常手动的,或者是构建自动化的一部分。

2.编写与调试

(0)技术选型
单元测试主要涉及到测试框架部分:
a)TestNG(Next Generation Java Testing)2
简介:是一个测试框架,其灵感来自于JUnit和NUnit,但引入了一些新功能,使其功能更强大
testng注解一览:

注解格式说明
@BeforeSuite被注释的方法将在所有测试运行前运行
@AfterSuite被注释的方法将在所有测试运行后运行
@BeforeTest被注释的方法将在测试运行前运行
@AfterTest被注释的方法将在测试运行后运行
@BeforeGroups被配置的方法将在列表中的gourp前运行。这个方法保证在第一个属于这些组的测试方法调用前立即执行。
@AfterGroups被配置的方法将在列表中的gourp后运行。这个方法保证在最后一个属于这些组的测试方法调用后立即执行。
@BeforeClass被注释的方法将在当前类的第一个测试方法调用前运行。
@AfterClass被注释的方法将在当前类的所有测试方法调用后运行。
@BeforeMethod被注释的方法将在每一个测试方法调用前运行。
@AfterMethod被注释的方法将在每一个测试方法调用后运行。

b)Mockito3
简介:java开发测试模拟框架。是一个针对于java的mocking框架。模拟和校验模拟结果
(1)建立测试类

正式开始编码之前请在相应开发工具中 下载TestNG插件 ,方便测试

同包下建立XxxTest.java文件
在这里插入图片描述
(2)编码和运行

/*
所有的测试方法的都要加上@Test注解并且只要是测试方法就不能够有参数
@Test注解的使用:
1.引入包import org.testng.annotations.Test;
2.当有多个测试方法时候,执行的顺序默认是按照字典序升序执行,
  也可以使用@Test(priority=1)的方式指定执行顺序。数值越小越先被执行
3.当有多个测试方法时候,有部分测试方法还没有完成编写,可以使用  
  @Test(enable=false),这样在运行时候,就不会执行该测试方法
*/
package com.xxx.app.appprocess;

import org.testng.annotations.Test;

public class AccessProcessImplTest
{
	//声明变量对象...
	
	//测试方法列
    @Test
    public void Xxx1Test()//测试方法的命名要注意符合规范  原来的方法名+场景+Test
    {
    	......
    }
    
	@Test
    public void Xxx2Test()
    {
    	......
    }
}

测试文件.xml文件的编写
在这里插入图片描述
可以参考官方文档4

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="classes" thread-count="1">
    <test name="MQTest">
        <classes>
            <class name=""/><!-- 新建的测试类类名-->
            <!-- 每新建一个测试类都要在此添加<class name="" />标签
            添加该文件的目的,当使用maven管理项目时候,可以将该配置文件引入到maven中。如果maven还配置了代码测试覆盖率工具,这样就可以把测试覆盖率统计出来。
			-->
        </classes>
    </test>


    <listeners><!-- 监听-->
        <listener class-name="org.uncommons.reportng.HTMLReporter" />
        <listener class-name="org.uncommons.reportng.JUnitXMLReporter" />
    </listeners>
</suite>

运行,该测试类上 右键run as TestNG test
在这里插入图片描述
测试结果:
其中‘ run: 1, Failures: 0 ’表示,1个成功0个失败

[TestNG] Running:
  C:\Users\Mr\AppData\Local\Temp\testng-eclipse--676935048\testng-customsuite.xml

hello TestNg
PASSED: XxxTest

===============================================
    Default XxxTest
    Tests run: 1, Failures: 0, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@45e35a2f: 53 ms
[TestNG] Time taken by [TestListenerAdapter] Passed:0 Failed:0 Skipped:0]: 1 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter@70ab4338: 5 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@256ee01c: 14 ms
[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@8ba0dd4: 6 ms

(3)Mockito在单元测试中的使用

一个问题
请大家思考下这个问题:如果一个单元测试中涉及到数据库的操作文件读写网络开销接口操作等等一系列耗时或者实现可能性小的操作,这种情况下我们该如何处理这些数据。
分析:本来单元测试就是一个个独立模块的测试,只测试代码的业务逻辑是否行的通,一旦单元测试牵扯到相互依赖的类,就要使用模拟类把需要用到的第三方对象模拟出来,这就是我理解的Mock的意义。

我们来看下来自引用博客的理解:

  1. 什么是Mock测试

    Mock测试是单元测试的重要方法之一。Mock测试就是在测试过程中,对于某些不易构造的对象(如HttpServletRequest必须在Servlet容器中才能构造出来),或者不易获取比较复杂的对象(如JDBC中的ResultSet对象),用一个虚拟的对象(Mock对象)来创建,以便测试的一种测试方法。
    Mock最大的功能就是帮你把单元测试的耦合分开,如果你的代码对于另一个类或者接口有依赖,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为,且默认这些依赖都是正确的,来测试你的代码是否正确。
    比如,存在以下一段代码依赖,当我们需要测试A类的时候,如果没有Mock,我们就需要把整个依赖树都构建出来:

uses
uses
uses
uses
A
B
C
D
E

而当我们用Mock时候,就可以将结构分解开来:

uses
uses
A
MockB
MockC
  1. Mock对象的使用范畴
    真实对象具有不可确定的行为,产生不可预测的结果(如:股票行情、天气预报);
    真实对象很难被创建;
    真实对象的某些行为很难被触发 ;
    真实对象实际上还不存在的等等

  2. Mockito和Mock的关系
    Mockito是java单元测试的开源的Mock框架。Mockito拥有非常少的API,所以开始使用Mockito时候,很便捷,因为只有一种创建mock的方式。只要记住在执行前打桩、而后在交互中验证。
    特点:
    可以mock具体的类,而不单单是接口;
    注解语法糖–@Mock;
    失败验证的堆栈跟踪完整、简洁;
    允许灵活有序的verify;
    支持详细用户号码的时间以及至少一次验证;
    支持自定义的参数匹配器;

  3. 使用Mocktio编写单元测试
    谈到模拟的时候只需要关心:设置测试数据、设定预期结果、验证结果

/*
1.类中导入常用包
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.testng.PowerMockObjectFactory;
2.如果涉及到静态类等,使用PowerMockito,并且在类头使用@PrepateForTest({这里是测试中使用到的静态类的预加载})
*/ 
@PrepareForTest({StaticClass.class})
@PowerMockIgnore({"javax.management.*"})
public class AccessProcessImplTest
{
   //声明对象
   private AccessProcessImpl accProcess;
   private RtcMsg rtcMsg;
   private IThreadModel threadModel;
   
   @Test
   public void Xxx()
   {
   	//1初始化
   	//Mockito.spy()模拟被测试类,会执行到被测试类内部
   	//Mockito.mock(class<T>);模拟对象,只有在调用的时候才会模拟
   	//@Mock注解,一般放在类的变量区域,这样对于所有的测试方法,该模拟的对象都是有效的,所以可能会导致多次调用现象,建议使用Mockito.mock()方式
   	accProcess = Mockito.spy(new AccessProcessImpl());
   	//2打桩
   	//模拟对象有时候会调用方法,其中的参数是使用参数匹配器的方式:Mockito.anyInt() Mockito.anyString() Mockito.any(class<T>)最后一种是自定义方式的参数匹配器
   	//thenReturn可能会返回自己设定的测试数据,有一点需要注意,模拟测试数据的时候,一定是要单纯的数据模拟,自己手动构造的数据,不能使用if for等语句块构造
   	Mockito.when().thenReturn();
   	
   	//3测试
   	accProcess.process(rtcMsg);//使用Mockito.spy()方式可以让模拟对象去执行对应的测试方法,同时又能够包含模拟对象
   	
   	//4验证
   	//有两种验证方式
   	//1)Mockito.verify来验证对象是否执行某个方法,执行了多少次(Mockito.times(n) n次 Mockito.atLeast(n) 至少n次 Mockito.never() 一次也没有)
   	//2)Assert.assertEquals( obj1 , obj2 );验证两个对象是否相等
   	Mockito.verify(threadModel, Mockito.times(1)).method();
   }
}

   //必须要写的,我理解的是工厂类,用来构建模拟对象
   @ObjectFactory
   public ITestObjectFactory getObjectFactory()
   {
   	return new PowerMockObjectFactory();
   }

3.小结

(1)单元测试的好处
经过近一周的学习,我感觉单元测试的编写,让我更好的理解了代码的运行逻辑,在此基础上也熟悉了好多插件的使用。
查找的资料表明:单元测试的好处不仅仅是我所总结的,还有重构、优化代码、集成测试等方面都有优势。
(2)对待单元测试的态度
无单测,不编码
测试驱动开发(Test Driven Developement)
(3)单元测试的覆盖率
在maven中加入jacoco插件,单元测试编写调试完成之后,只需要,maven install命令运行即可(在Eclipse中是在pom文件上右键 run as maven install)
在这里插入图片描述

此时,会自动在target中生成suit文件(注意在testng.xml文件中要添加相应的测试类,不然没添加的不会被统计覆盖率)
D:\Myworkspace…\badFileToMq\target\site\jacoco到相应工作空间目录下查找到target\site\jacoco\index.html文件,点开就是jacoco可视化覆盖率统计结果
在这里插入图片描述
(4)Mockito的覆盖率
时间有限,这点就不细致说明了。关键字 jacoco 单元测试覆盖率可以自行百度 google等。

如有表达有误之处,还望大家积极指出,谢谢!

4参考


  1. 单元测试 ↩︎

  2. testng教程 ↩︎

  3. Mock和Mockito简介 ↩︎

  4. 官方testng配置 文件 ↩︎

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值