简体   繁体   English

使用DateTimeOffset对象的单元测试类的正确方法?

[英]Correct way of unit-testing classes that use DateTimeOffset objects?

I would appreciate information or examples about how to correctly test code that uses DateTimeOffset instances. 我将非常感谢有关如何正确测试使用DateTimeOffset实例的代码的信息或示例。 I know the tests have to be deterministic. 我知道测试必须是确定性的。

So, how would one isolate the application from the DateTimeOffset classes ? 那么,如何将应用程序与DateTimeOffset类隔离开来呢? I would, of course, like to be able to use a fake DateTimeOffset.Now, etc. 当然,我希望能够使用假的DateTimeOffset.Now等。

In my tests, should I be using something like: 在我的测试中,我应该使用类似的东西:

var myDate = new DateTimeOffset(2016, 3, 29, 12, 20, 35, 93, TimeSpan.FromHours(-3));

Or would I instead be using a wrapper class like MyCustomDateTimeOffset ? 或者我会使用像MyCustomDateTimeOffset这样的包装类? Should I not use DateTimeOffset at all in my code and use a wrapper instead? 我的代码中根本不应该使用DateTimeOffset而是使用包装器吗?

As the fundamentals theorem says: 正如基本原理所说:

We can solve any problem by introducing an extra level of indirection. 我们可以通过引入额外的间接层来解决任何问题。

You don't really need a wrapper, all you need is to avoid DateTimeOffset.Now / DateTimeOffset.UtcNow . 你真的不需要一个包装器,你只需要避免使用DateTimeOffset.Now / DateTimeOffset.UtcNow

Here are a few ways you could handle that: 以下是您可以处理的几种方法:

  • If you use dependency injection, write an IClock interface which exposes the Now / UtcNow properties. 如果使用依赖注入,请编写一个公开Now / UtcNow属性的IClock接口。

     public interface IClock { DateTimeOffset Now { get; } DateTimeOffset UtcNow { get; } } internal class Clock : IClock { public DateTimeOffset Now => DateTimeOffset.Now; public DateTimeOffset UtcNow => DateTimeOffset.UtcNow; } 

    In your tests, you just mock the interface as you wish. 在您的测试中,您只需按照自己的意愿模拟界面。

  • If you'd rather keep using a static property, write a static type, let's say Clock , and use that. 如果你宁愿继续使用静态属性,写一个静态类型,比如说Clock ,然后使用它。

     public static class Clock { internal static Func<DateTimeOffset> DateTimeOffsetProvider { get; set; } = () => DateTimeOffset.Now; public static DateTimeOffset Now => DateTimeOffsetProvider(); public static DateTimeOffset UtcNow => DateTimeOffsetProvider().ToUniversalTime(); } 

    In your tests, you can substitute DateTimeOffsetProvider . 在测试中,您可以替换DateTimeOffsetProvider

    Here's a .NET 2 version: 这是一个.NET 2版本:

     public static class Clock { internal delegate DateTimeOffset DateTimeOffsetProviderDelegate(); internal static DateTimeOffsetProviderDelegate DateTimeOffsetProvider { get; set; } public static DateTimeOffset Now { get { return DateTimeOffsetProvider(); } } public static DateTimeOffset UtcNow { get { return DateTimeOffsetProvider().ToUniversalTime(); } } static Clock() { DateTimeOffsetProvider = delegate() { return DateTimeOffset.Now; }; } } 

As you won't know the value of DateTimeOffSet.Now, then all you can't assert that DateTimeOffSet.Now equals a value. 因为你不知道DateTimeOffSet.Now的值,所以你不能断言DateTimeOffSet.Now等于一个值。

You probably should refactor to use one of two methods: 您可能应该重构使用以下两种方法之一:

  • Dependency Injection 依赖注入
  • Interface and Wrappers 接口和包装

Dependency Injection (DI) 依赖注入(DI)

DI means instead of having the method determine the date, you pass it in. DI意味着不是让方法确定日期,而是传递它。

This method . 这种方法。 . .

public void DoSomething()
{
   var now = DateTimeOffSet.Now;
   // Do other stuff with the date
}

. . . would change to this method 会改变这种方法

public void DoSomething(DateTimeOffSet dtos)
{
   // Do other stuff with the date
}

Interface and Wrapper 接口和包装

Your other option (although in the end you would use DI with this too) is to create an Interface and a Wrapper. 你的另一个选择(虽然最后你也会使用DI)是创建一个接口和一个包装器。 Then use you the interface in your object instead of a concrete DateTimeOffSet, so you can then use MOQ or other testing library to moq the interface. 然后使用对象中的接口而不是具体的DateTimeOffSet,这样您就可以使用MOQ或其他测试库来设置接口。 Check out SystemWrapper ( https://github.com/jozefizso/SystemWrapper ) project for an example. 查看SystemWrapper( https://github.com/jozefizso/SystemWrapper )项目以获取示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM