Simulate a delay in execution in Unit Test using Moq

拈花ヽ惹草 提交于 2019-12-04 01:34:45

If you want a Moq mock to just sit and do nothing for a while you can use a callback:

Mock<IFoo> mockFoo = new Mock<IFoo>();
mockFoo.Setup(f => f.Bar())
       .Callback(() => Thread.Sleep(1000))
       .Returns("test");

string result = mockFoo.Object.Bar(); // will take 1 second to return

Assert.AreEqual("test", result);

I've tried that in LinqPad and if you adjust the Thread.Sleep() the execution time varies accordingly.

When you setup your mock you can tell the thread to sleep in the return func:

Mock<IMyService> myService = new Mock<IMyService>();

myService.Setup(x => x.GetResultDelayed()).Returns(() => {
    Thread.Sleep(100);
    return "result";
});

I could not get Moq version to work, so I ended up making something like this:

a small example using WaitHandle:

[TestFixture]
public class EventWaitHandleTests
{
    class Worker {
        private volatile bool _shouldStop;
        public EventWaitHandle WaitHandleExternal;

        public void DoWork ()
        {
            while (!_shouldStop)
            {
                Console.WriteLine("worker thread: working...");
                Thread.Sleep(1000);
                WaitHandleExternal.Set();
            }
        }

        public void RequestStop()
        {
            _shouldStop = true;
        }

    }

    [Test]
    public void WaitForHandleEventTest()
    {
        EventWaitHandle _waitHandle = new AutoResetEvent (false); // is signaled value change to true

        // start a thread which will after a small time set an event
        Worker workerObject = new Worker ();
        workerObject.WaitHandleExternal = _waitHandle;
        Thread workerThread = new Thread(workerObject.DoWork);

        // Start the worker thread.
        workerThread.Start();

        Console.WriteLine ("Waiting...");
        _waitHandle.WaitOne();                // Wait for notification
        Console.WriteLine ("Notified");

        // Stop the worker thread.
        workerObject.RequestStop();

    }

}

I like and voted for serup's solution. My answer is a version of his converted for use as a library.

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

/// <summary>
/// support halting a workflow and waiting for a finish request
/// </summary>
public class MockWorker
{
    private readonly DateTime? _end;
    private volatile bool _shouldStop;

    /// <summary>
    /// Create a worker object
    /// </summary>
    /// <param name="timeoutInMilliseconds">How long before DoWork will timeout.  default - Null will not timeout.</param>
    public MockWorker(int? timeoutInMilliseconds = null)
    {
        if (timeoutInMilliseconds.HasValue)
            _end = DateTime.Now.AddMilliseconds(timeoutInMilliseconds.Value);
    }

    /// <summary>
    /// Instruct DoWork to complete
    /// </summary>
    public void RequestStop()
    {
        _shouldStop = true;
    }

    /// <summary>
    /// Do work async will run until either timeoutInMilliseconds is exceeded or RequestStop is called.
    /// </summary>
    public async Task DoWorkAsync()
    {
        while (!_shouldStop)
        {
            await Task.Delay(100);
            if (_end.HasValue && _end.Value < DateTime.Now)
                throw new AssertFailedException("Timeout");
        }
    }

    /// <summary>
    /// Do work async will run until either timeoutInMilliseconds is exceeded or RequestStop is called.
    /// </summary>
    /// <typeparam name="T">Type of value to return</typeparam>
    /// <param name="valueToReturn">The value to be returned</param>
    /// <returns>valueToReturn</returns>
    public async Task<T> DoWorkAsync<T>(T valueToReturn)
    {
        await DoWorkAsync();
        return valueToReturn;
    }
}

I had a similiar situation, but with an Async method. What worked for me was to do the following:

 mock_object.Setup(scheduler => scheduler.MakeJobAsync())
  .Returns(Task.Run(()=> { Thread.Sleep(50000); return Guid.NewGuid().ToString(); }));
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!