Search code examples
c#.netunit-testingeventsthread-sleep

In UnitTest Thread.sleep(1300) is only waiting ~300ms


I am trying to test that calling SendMessage after a set amount of time (in my case 1300ms) will give the correct result in the event handler. However Thread.Sleep(1300) is not waiting 1300ms, it only waits for about 300ms.

Unit Test

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);
        }
    }
}

Class1

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);
        }

    }
}

The output I get is

Assert.AreEqual failed. Expected:<1300>. Actual:<302>.

Obviously I don't expect them to be equal, this is just for the example.

I have also tried System.Threading.Tasks.Task.Delay(1300).Wait();, but I get the same result.

How can I get the test thread to wait the right amount of time? Why doesn't Thread.Sleep work?


Solution

  • In your assert you're using:

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

    Try using the following instead:

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

    TimeSpan.TotalMilliseconds :

    Gets the value of the current TimeSpan structure expressed in whole and fractional milliseconds.

    TimeSpan.Milliseconds :

    Gets the milliseconds component of the time interval represented by the current TimeSpan structure.

    The reason it is returning 300ms is because milliseconds component of your TimeSpan is in fact 300 milliseconds, but also the seconds component of your TimeSpan is 1 second.