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 ...
随机推荐
- js访问php,返回数组时的注意事项
用ajax访问php脚本返回值是数组的时候,php端需要使用json_encode()函数进行转码成json字符串,js端需要用JSON.parse()来吧json字符串转换成数组或对象. 直接返回会 ...
- Oracle创建自增ID
先创建序列sequence create sequence S_User minvalue 1 nomaxvalue -- 或 maxvalue 999 start with 1 increment ...
- .Net Core 杂记
在学习.net core的路上,遇到很多坑,慢慢了解了.net core设计理念和设计思想(纯属跟人理解). 再此整理了之前写的一些学习笔记,后续也会把新的学习新的加上. 1..net core 跨平 ...
- C语言: 运算符,printf,scanf的用法
运算符/的运算结果和运算对象的数据类型有关,两个数都是in,则商就是int,取整数部分:被除数和除数中只要有一个或两个都是浮点型数据,则商也是浮点型,不去掉小数部分如:16/5 == 3:16/5.0 ...
- JavaScript对象详解
JavaScript中的数据类型作为javascript的核心,我们经常要用到,也是最基础的. javascript中有非常复杂的数据类型:包括对象(Object)数据类型,还有五个基本数据类型(N ...
- 使用Grunt构建自动化开发环境
1.准备工作 1)首页确保电脑上网,以及能够访问https://registry.npmjs.org/,因需从此网站中下载安装相应的插件; 2)电脑安装Node.js,Grunt及Grunt插件都是基 ...
- log4net 2.0.4有问题,AdoNetAppender会报错
坑死老子了 <appSettings> <add key="log4net.Internal.Debug" value="true"/> ...
- oracle 学习笔记(一)
1. 数据库原理 1.1. 数据库简介 1.1.1. 文件存储 对数据的存储需求一直存在.保存数据的方式,经历了手工管理.文件管理等阶段,直至数据库管理阶段. 文件存储方式保存数据的弊端: 缺乏对数据 ...
- Go简介
Go是Google开发的一种编译型,並發型,并具有垃圾回收功能的编程语言. 罗伯特·格瑞史莫(Robert Griesemer),罗勃·派克(Rob Pike)及肯·汤普逊于2007年9月开始设计Go ...
- nginx配置返回文本或json
有些时候请求某些接口的时候需要返回指定的文本字符串或者json字符串,如果逻辑非常简单或者干脆是固定的字符串,那么可以使用nginx快速实现,这样就不用编写程序响应请求了,可以减少服务器资源占用并且响 ...