TDD学习笔记【四】--- 如何隔离相依性 - 基本的可测试性
前言
什么是相依性
- 根据 id,取得存在数据源中的密码(仅存放经过 hash 运算后的结果)。
- 根据传入的密码,进行 hash 运算。
- 比对数据源回传的密码,与输入密码经过哈希运算的结果,是否吻合。
简单的程序代码如下(AccountDao与Hash的内容不是重点,为节省篇幅就先省略):
using System; public class Validation
{
public bool CheckAuthentication(string id, string password)
{
// 取得数据库中,id对应的密码
AccountDao dao = new AccountDao();
var passwordByDao = dao.GetPassword(id);
// 针对传入的password,进行hash运算
Hash hash = new Hash();
var hashResult = hash.GetHashResult(password);
// 对比hash后的密码,与数据库中的密码是否吻合
return passwordByDao == hashResult;
}
} public class AccountDao
{
internal string GetPassword(string id)
{
//连接DB
throw new NotImplementedException();
}
} public class Hash
{
internal string GetHashResult(string passwordByDao)
{
//使用SHA512
throw new NotImplementedException();
}
}
相依性的问题

单元测试的角度
[TestMethod()]
public void CheckAuthenticationTest()
{
Validation target = new Validation(); // TODO: 初始化为适当值
string id = string.Empty; // TODO: 初始化为适当值
string password = string.Empty; // TODO:初始化为适当值
bool expected = false; // TODO: 初始化为适当值
bool actual;
actual = target.CheckAuthentication(id, password);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("验证这个测试方法的正确性。");
}
弹性设计的角度
如何隔离对象之间的相依性
public interface IAccountDao
{
string GetPassword(string id);
} public interface IHash
{
string GetHashResult(string password);
} public class AccountDao : IAccountDao
{
public string GetPassword(string id)
{
throw new NotImplementedException();
}
} public class Hash : IHash
{
public string GetHashResult(string password)
{
throw new NotImplementedException();
}
} public class Validation
{
private IAccountDao _accountDao;
private IHash _hash; public Validation(IAccountDao dao, IHash hash)
{
this._accountDao = dao;
this._hash = hash;
} public bool CheckAuthentication(string id, string password)
{
// 取得数据库中,id对应的密码
var passwordByDao = this._accountDao.GetPassword(id);
// 针对传入的password,进行hash运算
var hashResult = this._hash.GetHashResult(password);
// 对比hash后的密码,与数据库中的密码是否吻合
return passwordByDao == hashResult;
}
}

原文可參考 Martin Fowler 的文章:Inversion of Control Containers and the Dependency Injection pattern
As a result I think we need a more specific name for this pattern. Inversion of Control is too generic a term, and thus people find it confusing. As a result with a lot of discussion with various IoC advocates we settled on the name Dependency Injection.
如何进行测试
[TestMethod()]
public void CheckAuthenticationTest()
{
IAccountDao accountDao = null;// TODO: 初始化为合适的值
Hash hash = null;// TODO: 初始化为合适的值
Validation target = new Validation(accountDao, hash);
string id = string.Empty; // TODO: 初始化为合适的值
string password = string.Empty;//TODO: 初始化为合适的值
bool expected = false;// TODO: 初始化为合适的值
bool actual;
actual = target.CheckAuthentication(id, password);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("验证这个测试的正确性。");
}
public class StubAccountDao : IAccountDao
{
public string GetPassword(string id)
{
return "Hello World";
}
}
接着用同样的方式,让 StubHash 的 GetHashResult,也回传 "Hello World",代表 hash 后的结果。程序代码如下:
public class StubHash : IHash
{
public string GetHashResult(string password)
{
return "Hello World";
}
}
聪明的读者朋友们,应该知道接下来就是来写单元测试的 3A pattern,单元测试程序代码如下:
[TestMethod()]
public void CheckAuthenticationTest()
{
//arrange
// 初始化StubAccountDao,来当作IAccountDao的执行对象
IAccountDao dao = new StubAccountDao();
// 初始化StubHash,来当作IStubHash的执行对象
IHash hash = new StubHash();
Validation target = new Validation(dao, hash);
string id = "随便写";
string password = "随便写";
bool expected = true;
bool actual;
//act
actual = target.CheckAuthentication(id, password);
//assert
Assert.AreEqual(expected, actual);
}

延伸思考
结论
补充
备注:这个系列是我毕业后时隔一年重新开始进入开发行业后对大拿们的博文摘要整理进行学习对自我的各个欠缺的方面进行充电记录博客的过程,非原创,特此感谢91 等前辈
TDD学习笔记【四】--- 如何隔离相依性 - 基本的可测试性的更多相关文章
- MySql学习笔记四
MySql学习笔记四 5.3.数据类型 数值型 整型 小数 定点数 浮点数 字符型 较短的文本:char, varchar 较长的文本:text, blob(较长的二进制数据) 日期型 原则:所选择类 ...
- 官网实例详解-目录和实例简介-keras学习笔记四
官网实例详解-目录和实例简介-keras学习笔记四 2018-06-11 10:36:18 wyx100 阅读数 4193更多 分类专栏: 人工智能 python 深度学习 keras 版权声明: ...
- C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...
- IOS学习笔记(四)之UITextField和UITextView控件学习
IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...
- java之jvm学习笔记四(安全管理器)
java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...
- Learning ROS for Robotics Programming Second Edition学习笔记(四) indigo devices
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
- Typescript 学习笔记四:回忆ES5 中的类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- ES6学习笔记<四> default、rest、Multi-line Strings
default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...
- muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制
目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ...
随机推荐
- Python:eval的妙用和滥用
时间 2014-07-08 13:05:24 CSDN博客 原文 http://blog.csdn.net/zhanh1218/article/details/37562167 主题 Python ...
- ThinkPHP框架之验证码
Think\Verify类可以支持验证码的生成和验证功能. 下面是最简单的方式生成验证码: $Verify = new \Think\Verify(); $Verify->entry(); 上面 ...
- jdk 安装 环境变量配置
右键选择 计算机→属性→高级系统设置→高级→环境变量 1.系统变量→新建 变量名:JAVA_HOME 变量值:(变量值填写你的jdk的安装目录,例如本人是 C:\Program Files\Java\ ...
- CMake
使用CMake编译跨平台静态库 http://www.tuicool.com/articles/3uu2Yj cmake命令 安装.用法简介 https://fukun.org/archives/04 ...
- fineui刷新父页面
protected override string AfterAddJS() { //TODO 重载这2个函数 可以控制新增和编辑之后执行的JS return AfterSaveJS_ReloadDa ...
- cross_domain
要传参数的页面 引用cross_domain.js 这个是另外一个工程(m)的地址 <script type="text/javascript" src="htt ...
- 影响postgresql性能的几个重要参数
转载 一篇蛮老的文章了,但是还是很有用,可参考修补. PG的配置文件是数据库目录下的postgresql.conf文件,8.0以后的版本可支持K,M,G这样的参数,只要修改相应参数后重新启动PG服务就 ...
- svn检出的时候报 Unable to connect to a repository at URL错误(摘自CSDN)
背景:1. SVN服务器:VisualSVN-Server-2.5.5: 2. SVN客户端:TortoiseSVN-1.7.6.22632-x64-svn-1.7.4.msi: 在S ...
- 【荐】如何规划 Nginx 网站目录的权限(用户,用户组,ssh,sftp)
从上一篇文章:PHP网站(nginx.php-fpm.mysql) 用户权限解析,可以学习了解到,nginx 和 php-fpm 的用户是如何运作的. 有个工作场景: 1.公司的一台 CentOS 服 ...
- socket.io简单入门(一.实现简单的图表推送)
引子:随着nodejs蓬勃发展,虽然主要业务系统因为架构健壮性不会选择nodejs座位应用服务器.但是大量的内部系统却可以使用nodejs试水,大量的前端开发人员转入全堆开发也是一个因素. 研究本例主 ...