在unit testing中处理DateTime.Now的策略
我的业务逻辑在周六或周日没有执行某些function。 我希望我的unit testing能够validation这些function是否已执行,但测试将在周六/周日失败。
我认为最简单的方法是让unit testing传达一条友好的信息,说明如果测试结果在周六/周日运行则无效。
用C#/ NUnit ……
Assert.That( DateTime.Now.DayOfWeek != DayOfWeek.Sunday && DateTime.Now.DayOfWeek != DayOfWeek.Saturday, "This test cannot be run on Saturday or Sunday");
试图嘲笑约会是否可行/可取? 是否有其他策略来处理这种情况?
试图嘲笑约会是否可行/可取?
是的,不仅是可行的,而且它是可靠地单独测试代码的唯一方法。 假设您要测试以下(无意义)方法:
public bool Foo() { return (DateTime.Now.DayOfWeek == DayOfWeek.Sunday); }
很明显,你无法测试它,因为它依赖于静态方法(静态Now属性更精确)。 很明显,像这样紧密耦合的组件不能单独进行unit testing。
现在考虑这种改进(与构造函数DI分离关注点):
private readonly Func _nowProvider; public SomeClass(Func nowProvider) { _nowProvider = nowProvider; } public bool Foo() { return (_nowProvider().DayOfWeek == DayOfWeek.Sunday); }
现在,unit testing更好更容易。 SomeClass
不再依赖于非确定性日期。 在实际的应用程序中,您显然会像这样实例化SomeClass
:
var s = new SomeClass(() => DateTime.Now); s.Foo();
在您的unit testing中,您将模拟它以便您可以validation这两种情况:
var subjectUnderTest = new SomeClass(() => new DateTime(2011, 1, 3)); var actual = subjectUnderTest.Foo(); // assertions, ...
您应该在系统时钟上创建一个抽象,因为您应该创建其他系统资源和外部资源的抽象,以便能够编写RTMunit testing 。
对系统时钟的抽象非常简单,看起来像这样:
public interface ISystemClock { DateTime Now { get; } }
应用程序中依赖于系统时钟的类通常应该具有ISystemClock
作为构造函数参数。 对于unit testing场景,您可以使用如下所示的ISystemClock
实现:
public class FakeSystemClock : ISystemClock { // Note the setter. public DateTime Now { get; set; } }
现在你可以在你的unit testing中使用这个假时钟,如下所示:
[TestMethod] [ExpectedException(typeof(InvalidOperationException), "Service should throw an exception when called on saturday.")] public void DoSomething_WhenCalledOnSaturday_ThrowsException() { // Arrange var saturday = new DateTime(2011, 1, 1); Assert.AreEqual(saturday.DayOfWeek, DayOfWeek.Saturday, "Test setup fail"); var clock = new FakeSystemClock() { Now = saturday }; var service = new Service(clock); // Act service.DoSomething(); }
在您的应用程序项目中,您可以定义实际使用系统时钟的ISystemClock
实现。 使用给定的ISystemClock
定义,它将如下所示:
public class RealSystemClock : ISystemClock { public DateTime Now => DateTime.Now; }
使用DI容器时,可以将其配置为连接类型,并在构造函数指定ISystemClock
参数时自动注入RealSystemClock
实例。
顺便说一句。 虽然您可以使用Func
委托来完成这一操作,但为此定义一个接口更加明确,并且对其他开发人员来说更具可读性。 除此之外,将DI容器中的所有内容连接起来会容易得多,因为它很容易以多个Func
依赖关系结束,所有这些都与“给我当前本地时间”不同。
我希望这有帮助。
上述就是C#学习教程:在unit testing中处理DateTime.Now的策略分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1033843.html