【问题标题】:In UnitTest Thread.sleep(1300) is only waiting ~300ms [duplicate]在 UnitTest Thread.sleep(1300) 只等待~300ms [重复]
【发布时间】:2019-11-25 02:12:17
【问题描述】:

我正在尝试测试在设定的时间(在我的情况下为 1300 毫秒)后调用 SendMessage 将在事件处理程序中给出正确的结果。但是Thread.Sleep(1300) 并没有等待 1300ms,它只等待了大约 300ms。

单元测试

using System;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using mvce;

namespace mvceTest
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            Class1 c = new Class1();

            string finalResult = "";

            c.AnEvent += (o, entry) => { finalResult = entry; };

            DateTime start = DateTime.Now;

            while (finalResult == "")
            {
                Thread.Sleep(1300);
                c.SendMessage("message");
            }

            DateTime end = DateTime.Now;

            Assert.AreEqual(1300, (end - start).Milliseconds);

            Assert.AreEqual("message", finalResult);
        }
    }
}

类 1

using System;

namespace mvce
{
    public class Class1
    {
        private readonly object _lock = new object();

        private event EventHandler<string> _anEvent;

        public event EventHandler<string> AnEvent
        {
            add
            {
                lock (_lock)
                {
                    _anEvent += value;
                }
            }
            remove
            {
                lock (_lock)
                {
                    _anEvent -= value;
                }
            }
        }

        public void SendMessage(string message)
        {
            _anEvent?.Invoke(this, message);
        }

    }
}

我得到的输出是

Assert.AreEqual 失败。预期:。实际:。

显然我不希望它们相等,这只是为了举例。

我也尝试过System.Threading.Tasks.Task.Delay(1300).Wait();,但得到了相同的结果。

如何让测试线程等待正确的时间?为什么Thread.Sleep 不起作用?

【问题讨论】:

  • 你是如何衡量~300ms的?
  • @SeM 这是断言告诉我的。
  • @MattEllen 这可能是XY problem。您真正想要实现的目标是什么?
  • @Nkosi 我必须测试事件的结果是否会受到调用SendMessage 所需时间的影响。
  • @MattEllen 那么我建议您编辑问题以澄清这一点。如果说得清楚,你会得到更好的回应。现在您更多地关注Thread.Sleep 问题,这会将注意力从实际问题上移开。提供minimal reproducible example

标签: c# .net unit-testing events thread-sleep


【解决方案1】:

在您使用的断言中:

Assert.AreEqual(1300, (end - start).Milliseconds);

尝试改用以下方法:

Assert.AreEqual(1300, (end - start).TotalMilliseconds);

TimeSpan.TotalMilliseconds

获取当前TimeSpan结构的值以整体表示 和小数毫秒。

TimeSpan.Milliseconds

获取由表示的时间间隔的毫秒分量 当前的 TimeSpan 结构。

它返回 300 毫秒的原因是因为 TimeSpan 的毫秒部分实际上是 300 毫秒,但 TimeSpan 的秒部分也是 1 秒。

【讨论】:

  • 太棒了。我没有意识到这就是 DateTime 的工作方式。谢谢!
  • 这也会给出不准确的结果(Assert.AreEqual 会失败)。
  • @SeM 在实际测试中我没有使用 AreEqual,这只是为了证明有什么区别。
  • 那么你可能应该问一个关于你实际使用什么的问题。
【解决方案2】:

您应该使用 TotalMilliseconds 而不是 Milliseconds。 此外,最好使用秒表来测量时间。

这段代码显示线程确实休眠了 1300 毫秒:

 static void Main(string[] args)
    {
        Class1 c = new Class1();

        string finalResult = "";

        c.AnEvent += (o, entry) => { finalResult = entry; };

        Stopwatch sw = new Stopwatch();
        DateTime start = DateTime.Now;

        while (finalResult == "")
        {
            sw.Start();
            Thread.Sleep(1300);
            var ms = sw.ElapsedMilliseconds;
            Console.WriteLine(ms);
            c.SendMessage("message");
        }
        DateTime end = DateTime.Now;
        Console.WriteLine((end - start).TotalMilliseconds);
}

【讨论】:

    猜你喜欢
    • 2018-07-13
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 2012-11-05
    • 1970-01-01
    相关资源
    最近更新 更多