框架重构:测试中的DateTime.Now
存在的问题
- DateTime.Now是C#语言中获取计算机的当前时间的代码;
- 但是,在对使用了DateTime.Now的方法进行测试时,由于计算机时间的实时性,期望值一直在变化。如:计算年龄。
public static class DateTimeExtensionMethods
{
public static int Age(this DateTime date)
{
DateTime now = DateTime.Now;
......
}
}
new DateTime(2008,8,12).Age().ShouldEqual(???);
解决方案一:给Age方法增加一个参数,将当前时间传进去
// method
public static int Age(this DateTime date, DateTime now){...}
// test
new DateTime(2008,8,12).Age(new DateTime(2017,8,13)).ShouldEqual(9);
缺点:
- 显示传入当前时间麻烦
- 多一个参数,维护成本也会增加
- 感觉怪怪的,不符合习惯
解决方案二:使用IoC框架实现
public interface ISystemClock
{
DateTime Now { get; }
}
public class SystemClock : ISystemClock
{
public DateTime Now
{
get { return DateTime.Now; }
}
}
public static class DateTimeExtensionMethods
{
public static int Age(this DateTime date)
{
DateTime now = IoC.Get<ISystemClock>().Now;
......
}
}
// 真实系统
IoC.Register<ISystemClock, SystemClock>();
// test
var mock = MockRepository.GenerateMock<ISystemClock>();
mock.Stub(x=>x.Now).Return(new DateTime(2017,8,13);
IoC.Register<ISystemClock>(mock);
缺点
- 需要使用IoC框架
- 操作繁琐,代码量有点多
解决方案三:使用委托(当前最佳方案)
public static class SystemClock
{
public static Func<DateTime> Now = () => DateTime.Now;
}
public static class DateTimeExtensionMethods
{
public static int Age(this DateTime date)
{
DateTime now = SystemClock.Now();
int age = now.Year - date.Year;
if (now.Month == date.Month)
age = (now.Day < date.Day) ? age - 1 : age;
else if (now.Month < date.Month)
age = age - 1;
return age;
}
}
[Subject(typeof(DateTime), "Age")]
public class when_convert_birthday_to_age
{
Establish context = () => SystemClock.Now = () => new DateTime(2013, 8, 25);
public class with_yesterday_is_birthday
{
Because of = () => result = new DateTime(1980, 8, 24).Age();
It 应该计算出正确的年龄 = () => result.ShouldEqual(33);
}
public class with_today_is_birthday
{
Because of = () => result = new DateTime(1980, 8, 24).Age();
It 应该计算出正确的年龄 = () => result.ShouldEqual(33);
}
public class with_tomorrow_is_birthday
{
Because of = () => result = new DateTime(1980, 8, 26).Age();
It 应该计算出正确的年龄 = () => result.ShouldEqual(32);
}
private static int result;
}
You can implement ICleanupAfterEveryContextInAssembly to perform cleanup after every context.
machine.specifications官网
// 每个测试执行完后,需把SystemClock.Now还原
public class ResetTheClock : ICleanupAfterEveryContextInAssembly
{
public void AfterContextCleanup()
{
SystemClock.Now = () => DateTime.Now;
}
}
框架重构:测试中的DateTime.Now的更多相关文章
- Rafy 领域实体框架设计 - 重构 ORM 中的 Sql 生成
前言 Rafy 领域实体框架作为一个使用领域驱动设计作为指导思想的开发框架,必然要处理领域实体到数据库表之间的映射,即包含了 ORM 的功能.由于在 09 年最初设计时,ORM 部分的设计并不是最重要 ...
- 重构 ORM 中的 Sql 生成
Rafy 领域实体框架设计 - 重构 ORM 中的 Sql 生成 前言 Rafy 领域实体框架作为一个使用领域驱动设计作为指导思想的开发框架,必然要处理领域实体到数据库表之间的映射,即包含了 OR ...
- nose测试中修改nose_html_reporting插件,使生成的html报告加入显示截图功能
使用nose框架在测试WEB UI自动化时,使用了第三方插件nose-html-reporting,来生成HTML报告,nose-html-reporting具体使用参见管网https://pypi. ...
- 在Spring Boot中使用Docker在测试中进行高级功能测试
最近又学到了很多新知识,感谢优锐课老师细致地讲解,这篇博客记录下自己所学所想. 想更多地了解Spring Boot项目中的功能测试吗?这篇文章带你了解有关在测试中使用Docker容器的更多信息. 本文 ...
- TechEmpower 13轮测试中的ASP.NET Core性能测试
应用性能直接影响到托管服务的成本,因此公司在开发应用时需要格外注意应用所使用的Web框架,初创公司尤其如此.此外,糟糕的应用性能也会影响到用户体验,甚至会因此受到相关搜索引擎的降级处罚.在选择框架时, ...
- 教你搭建SpringMVC框架( 更新中、附源码)
一.项目目录结构 二.SpringMVC需要使用的jar包 commons-logging-1.2.jar junit-4.10.jar log4j-api-2.0.2.jar log4j-core- ...
- Dynamics AX 2012 R2 在AIF服务契约中使用DateTime
Reinhard在AIF中使用DateTime作为服务契约的参数,与DotNet程序进行交互时,总是因为时区的问题,导致DotNet提交的System.DateTime与AIF中接收的DateTime ...
- 用 Python 测试框架简化测试
用 Python 测试框架简化测试 摘要:本文将向您介绍了三种流行 Python 测试框架(zope.testing,py.test,nose)的基本特性,并讨论新一代的测试风格. 最近出现了行业级的 ...
- MEF框架在Silverlight中应用(15)
原文:MEF框架在Silverlight中应用(15) MEF框架在Silverlight中应用 代码下载 MEF框架是微软提供的一个插件框架.应用概括为一句话:输入,输出,组合.下面是具体在Silv ...
随机推荐
- Browserify命令行参数
–outfile, -o: browserify日志打印到文件 –require, -r: 绑定模块名或文件,用逗号分隔 –entry, -e: 应用程序的入口 –ignore, -i: 省略输出 – ...
- POJ 1985 Cow Marathon(树的直径模板)
http://poj.org/problem?id=1985 题意:给出树,求最远距离. 题意: 树的直径. 树的直径是指树的最长简单路. 求法: 两遍BFS :先任选一个起点BFS找到最长路的终点, ...
- thinkphp getField("xxxxx", true); 得到一个字段所有值组成的的数组
很多时候我们只需要一张表里某个字段的值,组成的数组 $Channel = D('channel');$channelList = $Channel->order('user_name')-> ...
- mock数据
作为前端经常需要模拟后台数据,我们称之为mock.通常的方式为自己搭建一个服务器,返回我们想要的数据. 在这里我们使用node.js来实现 http://www.cnblogs.com/bsn-hua ...
- w3c标准盒模型与IE传统模型的区别
一.盒子模型(box model) 在HTML文档中的每个元素被描绘为矩形盒子.确定其大小,属性——比如颜色.背景.边框,及其位置是渲染引擎的目标. CSS下这些矩形盒子由标准盒模型描述.这个模型描述 ...
- eclipse使用lombok
1.下载lombok.jar,将lombok复制到eclipse的安装路径下,如图: 2.在eclipse.ini配置文件最后加入:-javaagent:D:\Program Files\Eclips ...
- 括号匹配——nyoj2
感觉自己的逻辑就像屎一样,这么简单的题目写了2个小时,以后写题还是要在纸上先列好提纲,不然如果你直接上机,遇到n多个bug的时候,容易迷失自我,去拆东补西的修bug而忽视了整片代码的逻辑的正确性. 在 ...
- nyoj42——连通图加欧拉(连通图板子)dfs
一笔画问题 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 zyc从小就比较喜欢玩一些小游戏,其中就包括画一笔画,他想请你帮他写一个程序,判断一个图是否能够用一笔画下 ...
- 添加git 忽略文件
在使用Git的过程中,我们喜欢有的文件比如日志,临时文件,编译的中间文件等不要提交到代码仓库,这时就要设置相应的忽略规则,来忽略这些文件的提交. Git 忽略文件提交的方法 有三种方法可以实现忽略Gi ...
- SpringXML方式配置bean的懒加载lazy-init
lazy-init(懒加载),表示该bean在容器初始化的时候不进行初始化. 例如: <bean name="role1" class="com.fz.entity ...