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 ...
随机推荐
- React的井字过三关(1)
React的井字过三关(1) 本文系React官方教程的Tutorial: Intro To React的笔记.由笔者用ES5语法改写. 在本篇笔记中,尝试用React构建一个可交互的井字棋游戏. 开 ...
- sqlserver 数据库索引建立原则
1.始终包含聚集索引 当表中不包含聚集索引时,表中的数据是无序的,这会降低数据检索效率.即使通过索引缩小了数据检索的范围,但由于数据本身是无序的,当从表中提取实际数据时,会产生频繁的定位问题,这也使得 ...
- 如何在latex 中插入EPS格式图片
如何在latex 中插入EPS格式图片 第一步:生成.eps格式的图片 1.利用visio画图,另存为pdf格式的图片 利用Adobe Acrobat裁边,使图片大小合适 另存为.eps格式,如下图所 ...
- [实战]MVC5+EF6+MySql企业网盘实战(29)——更新日志
摘要 NetDisk更新日志,及项目使用说明. 开发工具 Vs2013+mysql+ef6+mvc5 bug 1.在加载列表的时候,默认加载的所有,修改为,过滤逻辑删除的文件. 2.加载音乐,文档等分 ...
- SQL Server 积累
2016-11-24 sql语句修改某表某字段的数据类型和字段长度: 问题是在修改老功能中暴露出来的,我修改了图片上传功能,结果报图片路径超出数据库字段规定长度,我检查数据库后发现之前设计数据库的人将 ...
- 如何做出透明背景的flash动画
最近碰到了一个问题,做动画时怎么设置透明背景,字是白色的,网上搜了一下,发现可以这样做 在插入的flash代码中加入这一行代码就可以实现了 <param name="wmode&quo ...
- linux第二天
由于今天公司事情比较多,今天基本没有自学.了解了一下type命令:主要是显示命令类型的命令.linux命令分为内置命令和外部命令两种.内置命令就shell内置的命令,外部命令,就是需要有系统存在一个名 ...
- 项目vue2.0仿外卖APP(五)
header组件 vue-resourse应用 https://github.com/pagekit/vue-resource vue-resource是Vue.js的一款插件,它可以通过XMLHtt ...
- 泛型DAO与泛型Service
泛型Dao与Service 看了几个帖子,泛型Dao与Service的主要目的就是要减少重复代码.具体的说明如下: 1. 定义一个BaseDao接口,此接口包含了一些通用的DAO操作,例如:增加.删除 ...
- Delphi Code Editor 之 编辑器选项
Delphi Code Editor 之 编辑器选项 可从Code Editor的右键菜单中选择“Properties”菜单项来查看编辑器选项.也可以从主菜单[Tools | Editor Optio ...