测试篇——初探单元测试

初探单元测试

目录:

  • 单元测试的核心意义

  • 单元测试的特色

  • 一个简单的单元测试demo

  • 构建可测试的代码以及初探Mock框架NSubstitute

 

单元测试的核心意义

  • 验证代码健壮性,无 Bug
  • 项目升级,重构后涉及到旧的逻辑,保证以旧逻辑的稳定运行

单元测试的特色

  • 单元测试可重复运行
  • 单元测试持续长期有效,而且返回结果一致
  • 单元测试在内存中运行,不会依赖外部组建(例如真实的数据库,真实的文件等)
  • 单元测试能够快速返回结果
  • 一个测试方法只测试一个问题(最小的粒度)

一个简单的单元测试demo

  • 这里建立一个类 Product 表明商品; ProductCollection 表明配送的商品集合, DistributeProduct 方法根据传入的商品 Id 集合表明须要配送的商品(具体看项
    目代码)数据库

  • 建立一个基于 Framework 的单元测试项目 MyUnitTestApplication ,添加一个单元测试类 ProductCollectionTests , ,添加一个单元测试方
    法 ProductCollction_DistributeProduct_Test 编程

    • 注意点 1 :单元测试方法命名规范通常是 测试主体 _ 期待返回结果 _ 传入参数。
    • 注意点 2 :单元测试类须要添加 [TestClass] 特性,单元测试方法须要 [TestMethod] 特性修饰
    • 在单元测试的方法体内右键运行单元测试,以下图所示,能够在右侧测试资源管理器中看到看到运行结果;例如把第三个断言修改为一个错误的结果,右
      键运行单元测试,就会出现测试未经过显示。框架

    • 这样一个最简单的单元测试就写完了,假如未来有人修改了 DistributeProduct 方法,再将这个单元测试运行一遍就能够验证修改是否存在 Bug.单元测试

构建可测试性的代码

  • 关于 demo 的依赖性问题:单元测试的用例可以成功运行取决于内部全部逻辑正常运行,例如上面 demo 中的测试核心是 DistributeNotice 对象,由于测试

的是它的 ToNotice 方法向外部发送通知消息。因此这里的 ProductCollection 对象依赖于 DistributeNotice 对象。可是,通常向外部发送信息须要 一些配置以测试

及 第三方的代理类(外部依赖)。例如以下图所示: DirstributeNotice 对象依赖着 ConfigurationManager 和 EmailSend 。此时单元测试已经不能进行了,由于需
要考虑其余的外在因素。
spa

  •   

     

  • 咱们的解决方案是:此时咱们能够添加一个 间接层。让本来依赖于 类或者 外部资源的对象抽象成依赖于它们的 接口,而后经过接口动态生成一个模拟的实现
    类。(这也是设计原则中所谓的 面向接口编程)因而咱们的依赖关系变为下图:设计

 

  • 修改咱们的代码,将实现类抽象成为接口;

基于接口重写编写单元测试,这里咱们用到了 Mock 接口单元测试,使用了开源的 Mock 框架 NSubstitute 。(测试过程当中替代真实对象的内存级别虚
拟对象)3d

  • 因此,单元测试的关键是面向接口,面向抽象。使各个组件,各个类依赖于接口,当代码耦合度太高将没法进行单元测试。
  • 当咱们须要测试一些类中受保护的方法测试时候,将会遇到下面的问题:
    •  在咱们实现业务过程当中,在类的内部常常会出现一些受保护的方法,而后测试类只会有一个公共的入口,此时咱们要怎样测试这些受保护的方

      法的业务逻辑呢?例以下图所示:咱们在咱们的 ProductCollection 集合类中添加一个方法 ValidatorProduct , ,根据产品的编号,判断产品的数量和价格是否合适,从而代理

      判断这个产品是否合适。在编写方法过程当中,咱们遵循单一职责原则,将验证逻辑碎片化以备未来扩展和重用,可是这些逻辑都是重要逻辑,咱们想
      要测试它们,然而咱们只有一个公共的方法入口 ValidatorProduct ,咱们不能单独的测试其中一个的逻辑。
      对象

此时咱们的解决方案是:咱们能够在测试环境下,提供一个继承于测试类的子类,在子类中提供这些方法的可测试版本。以下图所示:咱们创建了一个子

类 ProductCollectionAccessibility , ,经过继承的方式,在 ValidatorPriceAccessibility 方法中和 ValidatorNumberAccessibility 分别测试父类的验证产品价格和数
量的方法。

咱们常常须要完善咱们的测试用例,

  • 咱们的代码完成后会持续的进行修改,重构。在这个过程当中,代码会进行修改,从而会对之前的代码形成影响。此时咱们就须要一个保障。这个保证就是

单元测试,基于一个测试用例很完善的单元测试项目,咱们修改后,只须要将单元测试从新运行一遍,就能够保证重构修改代码是否有 Bug ,是否有副做
用。

  • 单元测试不单单验证代码正确性,无 Bug, 也保证了代码在生命周期中一直被完善和重构,让其愈来愈有价值,不会成为公司的技术债务。
相关文章
相关标签/搜索