Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 由于“System.DateTime”的准确性,单元测试在成组运行时运行过快_C#_Visual Studio 2010_Unit Testing_Testing_Poco - Fatal编程技术网

C# 由于“System.DateTime”的准确性,单元测试在成组运行时运行过快

C# 由于“System.DateTime”的准确性,单元测试在成组运行时运行过快,c#,visual-studio-2010,unit-testing,testing,poco,C#,Visual Studio 2010,Unit Testing,Testing,Poco,我正在运行一个很好的单元测试列表,它检查各种不同的类get和set。我遇到了一个小问题,我的测试运行得太快了 作为一个简单的例子,单元测试从用注释模仿博客开始 Blog b = new Blog("Comment"); 这将设置在博客中添加新评论的日期时间。然后我正在测试在博客中添加评论 b.addComment(comment); 在测试结束时,我主张使用以下方法添加测试: Assert.AreEqual(x, b.Comments.OrderByDescending(x => x.

我正在运行一个很好的单元测试列表,它检查各种不同的类get和set。我遇到了一个小问题,我的测试运行得太快了

作为一个简单的例子,单元测试从用注释模仿博客开始

Blog b = new Blog("Comment");
这将设置在博客中添加新评论的日期时间。然后我正在测试在博客中添加评论

b.addComment(comment);
在测试结束时,我主张使用以下方法添加测试:

Assert.AreEqual(x, b.Comments.OrderByDescending(x => x.CreatedDate).First().Comment;
就目前情况而言,当在隔离状态下运行时,这种情况就会发生。但是,当测试在一组测试中运行时,这将失败,因为两个注释具有完全相同的日期时间。值得注意的是,以下内容将通过,因为它将按默认顺序进行排序

Assert.AreEqual(x, b.Comments.OrderBy(x => x.Created).Last().Comment;
我最初的想法是它怎么会失败?Utc有一个滴答声函数,精确到百万分之一秒。经过一些研究,我发现系统日期时间仅精确到10-15毫秒,所以这是我的问题

我的问题是,什么是最好的解决方案?
我可以添加线程;每一个测试,但如果我运行1000个测试,现在是20秒?其他人是如何绕过这个问题的?

您的课程依赖于外部资源,即当前系统时间。因此,您并不是孤立地测试类,这会给您带来所面临的问题。您应该模拟DateTime。现在一些单元测试框架允许模拟静态成员,例如,或创建抽象依赖项,这将为您的类提供时间:

public interface ITimeProvider
{
    DateTime CurrentTime { get; }
}
正如Mark Seemann所建议的,您可以使用此抽象的静态实例来避免将此依赖关系传递给需要获取当前时间的每个类,但这将使依赖关系隐式化,因此由您决定采用哪种方式:

public class TimeProvider : ITimeProvider
{
    private static ITimeProvider _instance = new TimeProvider();

    private TimeProvider() { }

    public static ITimeProvider Instance 
    {
        get { return _instance; }
        set { _instance = value; } // allows you to set mock
    }

    public DateTime CurrentTime
    {
        get { return DateTime.Now; }
    }
}
使用起来很容易

var date = TimeProvider.Instance.CurrentTime;

您的类依赖于外部资源,即当前系统时间。因此,您并不是孤立地测试类,这会给您带来所面临的问题。您应该模拟DateTime。现在一些单元测试框架允许模拟静态成员,例如,或创建抽象依赖项,这将为您的类提供时间:

public interface ITimeProvider
{
    DateTime CurrentTime { get; }
}
正如Mark Seemann所建议的,您可以使用此抽象的静态实例来避免将此依赖关系传递给需要获取当前时间的每个类,但这将使依赖关系隐式化,因此由您决定采用哪种方式:

public class TimeProvider : ITimeProvider
{
    private static ITimeProvider _instance = new TimeProvider();

    private TimeProvider() { }

    public static ITimeProvider Instance 
    {
        get { return _instance; }
        set { _instance = value; } // allows you to set mock
    }

    public DateTime CurrentTime
    {
        get { return DateTime.Now; }
    }
}
使用起来很容易

var date = TimeProvider.Instance.CurrentTime;

完全同意,我忽略了嘲弄约会时间。只是前瞻性思考,例如,我在测试开始时生成一个存根博客,这也需要一个日期时间,我应该如何或在哪里存根博客以避免使用相同的“模拟”时间?@Heberda你正在为博客编写测试?如果是的话,那么你不应该把它存根。汉克斯:我认为我这方面的措辞很糟糕。谢谢你的快速回复。完全同意,我忽略了嘲弄约会时间。只是前瞻性思考,例如,我在测试开始时生成一个存根博客,这也需要一个日期时间,我应该如何或在哪里存根博客以避免使用相同的“模拟”时间?@Heberda你正在为博客编写测试?如果是的话,那么你不应该把它存根。汉克斯:我认为我这方面的措辞很糟糕。谢谢你的快速回复。对我来说,这说明你的代码被破坏了。在现实世界中完全有可能发生失败,因为两条注释的日期时间完全相同。在这种情况下失败是正确的行为吗?我不敢说。两个用户在15毫秒内添加评论的可能性有多大?我认为这取决于您为谁构建服务。我们可能最多有100个不经常使用的用户,例如,他们每小时登录一次……当然。。。但它可能会发生。。。这应该是一个错误吗?我想这是另一个开发者必须做出的艰难决定。不过,这是值得考虑的。虽然这可能是我大部分测试中考虑的一个测试,但它绝对是不需要的。干杯。对我来说,这说明你的密码被破解了。在现实世界中完全有可能发生失败,因为两条注释的日期时间完全相同。在这种情况下失败是正确的行为吗?我不敢说。两个用户在15毫秒内添加评论的可能性有多大?我认为这取决于您为谁构建服务。我们可能最多有100个不经常使用的用户,例如,他们每小时登录一次……当然。。。但它可能会发生。。。这应该是一个错误吗?我想这是另一个开发者必须做出的艰难决定。不过,这是值得考虑的。虽然这可能是我大部分测试中考虑的一个测试,但它绝对是不需要的。干杯