存在的问题

  • 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的更多相关文章

  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. LeetCode——4Sum

    1. Question Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + ...

  2. LeetCode——Nth Digit

    Question Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... ...

  3. 《用 Python 学微积分》笔记 1

    <用 Python 学微积分>原文见参考资料 1. 1.多项式 f(x)=x3-5x2+9 def f(x): return x**3 - 5*x**2 + 9 print f(3) pr ...

  4. codeforces208E Blood Cousins

    题目链接:codeforces208E 正解:$dsu$ $on$ $tree$ 解题报告: 又是一波$dsu$ $on$ $tree$咯… $p$级$cousin$其实就是对于$x$的$p$级祖先统 ...

  5. xshell5使用ssh连接阿里云服务器

    这里有两种方式,一种是在阿里云的控制台里面进行,另一种是在Xshell里面生成密钥. 阿里云控制台密钥对 点击右上方的创建密钥对 在阿里云里面生成较为简单,点击该页面右上方的“创建密钥对”,在另一个页 ...

  6. [Vue]组件——组件的data 必须是一个函数

    普通的Vue实例data是一个对象: data: { count: 0 } 组件的data是一个方法: data: function () { return { count: 0 } } 详情见官网: ...

  7. go-statsd项目

    linux命令: 进程:top 收包丢包:netstat -su[c持续输出] go tool pprof: 我们可以使用go tool pprof命令来交互式的访问概要文件的内容.命令将会分析指定的 ...

  8. MVC 后台调用JS

    示例控制器: public ActionResult Index()        {            ViewBag.js = "<script type='text/java ...

  9. vim 的寄存器

    If you've been following my series on Vim, it should be clear now that Vim has a pretty clear philos ...

  10. cJONS序列化工具解读二(数据解析)

    cJSON数据解析 关于数据解析部分,其实这个解析就是个自动机,通过递归或者解析栈进行实现数据的解析 /* Utility to jump whitespace and cr/lf *///用于跳过a ...