存在的问题

  • DateTime.Now是C#语言中获取计算机的当前时间的代码;
  • 但是,在对使用了DateTime.Now的方法进行测试时,由于计算机时间的实时性,期望值一直在变化。如:计算年龄。
  1. public static class DateTimeExtensionMethods
  2. {
  3. public static int Age(this DateTime date)
  4. {
  5. DateTime now = DateTime.Now;
  6. ......
  7. }
  8. }
  1. new DateTime(2008,8,12).Age().ShouldEqual(???);

解决方案一:给Age方法增加一个参数,将当前时间传进去

  1. // method
  2. public static int Age(this DateTime date, DateTime now){...}
  3. // test
  4. new DateTime(2008,8,12).Age(new DateTime(2017,8,13)).ShouldEqual(9);

缺点:

  • 显示传入当前时间麻烦
  • 多一个参数,维护成本也会增加
  • 感觉怪怪的,不符合习惯

解决方案二:使用IoC框架实现

  1. public interface ISystemClock
  2. {
  3. DateTime Now { get; }
  4. }
  5. public class SystemClock : ISystemClock
  6. {
  7. public DateTime Now
  8. {
  9. get { return DateTime.Now; }
  10. }
  11. }
  1. public static class DateTimeExtensionMethods
  2. {
  3. public static int Age(this DateTime date)
  4. {
  5. DateTime now = IoC.Get<ISystemClock>().Now;
  6. ......
  7. }
  8. }
  1. // 真实系统
  2. IoC.Register<ISystemClock, SystemClock>();
  1. // test
  2. var mock = MockRepository.GenerateMock<ISystemClock>();
  3. mock.Stub(x=>x.Now).Return(new DateTime(2017,8,13);
  4. IoC.Register<ISystemClock>(mock);

缺点

  • 需要使用IoC框架
  • 操作繁琐,代码量有点多

解决方案三:使用委托(当前最佳方案)

  1. public static class SystemClock
  2. {
  3. public static Func<DateTime> Now = () => DateTime.Now;
  4. }
  1. public static class DateTimeExtensionMethods
  2. {
  3. public static int Age(this DateTime date)
  4. {
  5. DateTime now = SystemClock.Now();
  6. int age = now.Year - date.Year;
  7. if (now.Month == date.Month)
  8. age = (now.Day < date.Day) ? age - 1 : age;
  9. else if (now.Month < date.Month)
  10. age = age - 1;
  11. return age;
  12. }
  13. }
  1. [Subject(typeof(DateTime), "Age")]
  2. public class when_convert_birthday_to_age
  3. {
  4. Establish context = () => SystemClock.Now = () => new DateTime(2013, 8, 25);
  5. public class with_yesterday_is_birthday
  6. {
  7. Because of = () => result = new DateTime(1980, 8, 24).Age();
  8. It 应该计算出正确的年龄 = () => result.ShouldEqual(33);
  9. }
  10. public class with_today_is_birthday
  11. {
  12. Because of = () => result = new DateTime(1980, 8, 24).Age();
  13. It 应该计算出正确的年龄 = () => result.ShouldEqual(33);
  14. }
  15. public class with_tomorrow_is_birthday
  16. {
  17. Because of = () => result = new DateTime(1980, 8, 26).Age();
  18. It 应该计算出正确的年龄 = () => result.ShouldEqual(32);
  19. }
  20. private static int result;
  21. }

You can implement ICleanupAfterEveryContextInAssembly to perform cleanup after every context.

machine.specifications官网

  1. // 每个测试执行完后,需把SystemClock.Now还原
  2. public class ResetTheClock : ICleanupAfterEveryContextInAssembly
  3. {
  4. public void AfterContextCleanup()
  5. {
  6. SystemClock.Now = () => DateTime.Now;
  7. }
  8. }

框架重构:测试中的DateTime.Now的更多相关文章

  1. Rafy 领域实体框架设计 - 重构 ORM 中的 Sql 生成

    前言 Rafy 领域实体框架作为一个使用领域驱动设计作为指导思想的开发框架,必然要处理领域实体到数据库表之间的映射,即包含了 ORM 的功能.由于在 09 年最初设计时,ORM 部分的设计并不是最重要 ...

  2. 重构 ORM 中的 Sql 生成

    Rafy 领域实体框架设计 - 重构 ORM 中的 Sql 生成   前言 Rafy 领域实体框架作为一个使用领域驱动设计作为指导思想的开发框架,必然要处理领域实体到数据库表之间的映射,即包含了 OR ...

  3. nose测试中修改nose_html_reporting插件,使生成的html报告加入显示截图功能

    使用nose框架在测试WEB UI自动化时,使用了第三方插件nose-html-reporting,来生成HTML报告,nose-html-reporting具体使用参见管网https://pypi. ...

  4. 在Spring Boot中使用Docker在测试中进行高级功能测试

    最近又学到了很多新知识,感谢优锐课老师细致地讲解,这篇博客记录下自己所学所想. 想更多地了解Spring Boot项目中的功能测试吗?这篇文章带你了解有关在测试中使用Docker容器的更多信息. 本文 ...

  5. TechEmpower 13轮测试中的ASP.NET Core性能测试

    应用性能直接影响到托管服务的成本,因此公司在开发应用时需要格外注意应用所使用的Web框架,初创公司尤其如此.此外,糟糕的应用性能也会影响到用户体验,甚至会因此受到相关搜索引擎的降级处罚.在选择框架时, ...

  6. 教你搭建SpringMVC框架( 更新中、附源码)

    一.项目目录结构 二.SpringMVC需要使用的jar包 commons-logging-1.2.jar junit-4.10.jar log4j-api-2.0.2.jar log4j-core- ...

  7. Dynamics AX 2012 R2 在AIF服务契约中使用DateTime

    Reinhard在AIF中使用DateTime作为服务契约的参数,与DotNet程序进行交互时,总是因为时区的问题,导致DotNet提交的System.DateTime与AIF中接收的DateTime ...

  8. 用 Python 测试框架简化测试

    用 Python 测试框架简化测试 摘要:本文将向您介绍了三种流行 Python 测试框架(zope.testing,py.test,nose)的基本特性,并讨论新一代的测试风格. 最近出现了行业级的 ...

  9. MEF框架在Silverlight中应用(15)

    原文:MEF框架在Silverlight中应用(15) MEF框架在Silverlight中应用 代码下载 MEF框架是微软提供的一个插件框架.应用概括为一句话:输入,输出,组合.下面是具体在Silv ...

随机推荐

  1. dp_c_区间dp_g

    You Are The One 题意:有n个人准备按顺序上台,上台前有个小黑屋(先进后出,即栈),可以被安排进去等待,也可以直接上台,一个人一旦被安排进去,后面的人就可以先上台(小黑屋无限大).每个人 ...

  2. [PyTorch]PyTorch/python常用语法/常见坑点

    目录 1. make_grid() 2. join与os.path.join() 3. 读文件写文件 4. json操作 5. tensorboard使用 6. python shutil.move ...

  3. 算数基本定理 - nefu 118

    算数基本定理 每个大于1的正整数都可以被唯一分解为素数的成绩,在乘积中的素因子按照非降序排列 a = p1^a1 * p2^a2 * ... pn^an; b = p1^b1 * p2^b2 * .. ...

  4. 解题报告:hdu1159 common consequence LCS裸题

    2017-09-02 17:07:42 writer:pprp 通过这个题温习了一下刚学的LCS 代码如下: /* @theme:hdu1159 @writer:pprp @begin:17:01 @ ...

  5. 打开PS是出现“该内存不能为read”是怎么回事?

    打开PS是出现“该内存不能为read”是怎么回事? 答:内存不能为read修复工具可以有效修复计算机运行应用程序时提示:该内存不能为read要终止程序的问题,一般XP系统才会出现这个问题. 指令修复法 ...

  6. 51Nod 1521 一维战舰

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1521 思路:先计算出一开始最多能放多少艘战舰,然后每次输入一个点后,找到 ...

  7. DLL注入之SHELLCODE数据转换

    #include "stdafx.h" #include <stdio.h> #include <string.h> #include <conio. ...

  8. 面试代码基础(一)从strstr说起

    对于写程序要注意:要能在面试官的提示下把代码写出来(把思想实现的能力)!还要注意边界检查!递归找到出口! 开场来个简单字符串匹配 int strstr(char* target,char* sourc ...

  9. no crontab for root 解决方案

    root用户下 输入 crontab -l 显示 no crontab for root  例如: [root@localhost ~]# crontab -l no crontab for root ...

  10. 手机端页面自适应解决方案—rem布局(该方案目前已过时)

    转自:https://segmentfault.com/a/1190000004705207 相信很多刚开始写移动端页面的同学都要面对页面自适应的问题,当然解决方案很多,比如:百分比布局,弹性布局fl ...