To Make Your App Loose Coupling And Test-able


单元测试的引入

TDD(测试驱动开发)将单元测试放到了一项工程的第一位,我觉得是工程师们对产品质量的不稳定性的一次深刻反思。既然产品质量、代码质量如此重要,与其反反复复的产生bug、回归测试、修改bug,不如一开始我们就动手测试它。当然,这次,我可不是要谈怎么做TDD。本文是想给那些有想着手做单元测试的开发者们却又没有好方案的一个指引。若你已经较为熟悉,也不妨看看我们想的是否一致。

为什么一些开发人员讨厌写单元测试

我想,大概是没有找到编写真正单元测试的方法。究其原因,无外乎有以下几点:

确实挺令人头疼的,我可不想为了单元测试而写这样的单元测试,因为我知道,那都是“骗人的”。

什么是理想的单元测试

当然,这是我个人的看法。我觉得它是这样的:

组件单元可测性与Moq

那得必须说到Moq组件了。Moq就是单元测试最佳助手,它是完全开源的,可到github上搜索。Moq重新阐述了单元测试的含义及重要性,它认为所谓的Mock,就是要模仿一些被测组件所依赖的组件的行为,来测试被测组件在各种工况下是否正常工作。所以,并不是常人所说的那样,仅仅mock数据而已,反而,我觉得最重要的却是行为。

要想写出可测试的组件单元,有很多种途径,但最佳实践方式我觉得还是“面向接口编程”,这也是Moq所推荐的做法。Moq之于.NET,只支持mock那些virtual/abstract的部件,而Interface是天生具备的这些特性的,所以面向接口编程是将你的程序变为可测、易测的第一步。

IOC(DI)与Moq

这两者本质上并没有任何关系,它们的方向点甚至都是不同的;一个用以探寻组件间低耦合依赖的最佳实践,另一个用来探寻单元测试的完美之道。其实往深处一想,他们有一个共同的概念在里面:“Dependency”。IOC所谓的依赖大多数是接口形式的依赖,Moq是模拟被测组件所需要的各种依赖;那么能结合IOC和Moq,在单元测试的时候,让IOC容器来自动管理被测组件所需要的依赖么?这个想法已被另一个开源的IOC组件Autofac捆绑实现。可见多往深处想想,信息量往往很大。

Autofac不要仅仅用来做与单元测试的东西,不然你就太侮辱它了。看本文所要聊的其实就是用Autofac+Moq来做一个组件间低耦合、可测试的应用程序。前者用来解决低耦合,后者用来解决单元测试编写与执行。

Autofac与Moq实现的单元测试

如果你是直接跳到这一小节的,我觉得你可能太着急了,因为理论是实践的重中之重,或许你应该看看前面的内容。 首先,我们需要的包有:Autofac、Autofac.Configuration、Autofac.Extras.Moq、Moq。资源都可以通过Nuget或github获得。

我们要实现什么功能

一个很小的demo,很简单,我有一个console app,需要执行一个功能:计算两个整形数字“和”与“差”的乘积,将结果以通知的形式打印到控制台。即:Print((a+b)*(a-b)).

我们如何设计这个系统


说明:

实现各个组件之后,我们在Console Client中加入如下代码,标识其核心业务逻辑:

说明:
OKay,程序已经可以正常Run起来了,结果也是正确的。

我们如何测试这个系统

为了避免本文是TDD相关的嫌疑,我将单元测试放在了最后,你完全可以在系统设计完成后就着手单元测试。结合Autofac + Moq,测试该业务功能的代码看起来是下面这样的(请基于注释理解即可):

(打赏)

If you want to pay for this
I will list your account name here.
HA HA!