Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simulate a delay in execution in Unit Test using Moq

Tags:

I'm trying to test the following:

protected IHealthStatus VerifyMessage(ISubscriber destination) {     var status = new HeartBeatStatus();      var task = new Task<CheckResult>(() =>     {         Console.WriteLine("VerifyMessage(Start): {0} - {1}", DateTime.Now, WarningTimeout);         Thread.Sleep(WarningTimeout - 500);         Console.WriteLine("VerifyMessage(Success): {0}", DateTime.Now);         if (CheckMessages(destination))         {             return CheckResult.Success;         }          Console.WriteLine("VerifyMessage(Pre-Warning): {0} - {1}", DateTime.Now, ErrorTimeout);         Thread.Sleep(ErrorTimeout - 500);         Console.WriteLine("VerifyMessage(Warning): {0}", DateTime.Now);         if (CheckMessages(destination))         {             return CheckResult.Warning;         }          return CheckResult.Error;     });      task.Start();      task.Wait();     status.Status = task.Result;      return status; } 

with the following unit test:

public void HeartBeat_Should_ReturnWarning_When_MockReturnsWarning() {     // Arrange     var heartbeat = new SocketToSocketHeartbeat(_sourceSubscriber.Object, _destinationSubscriber.Object);     heartbeat.SetTaskConfiguration(this.ConfigurationHB1ToHB2_ValidConfiguration());      // Simulate the message being delayed to destination subscriber.     _destinationSubscriber.Setup(foo => foo.ReceivedMessages).Returns(DelayDelivery(3000, Message_HB1ToHB2()));      // Act     var healthStatus = heartbeat.Execute();      // Assert     Assert.AreEqual(CheckResult.Warning, healthStatus.Status); } 

Message_HB1ToHB2() just returns a string of characters and the "Delay Delivery" method is

private List<NcsMessage> DelayDelivery(int delay, string message) {     var sent = DateTime.Now;     var msg = new NcsMessage()     {         SourceSubscriber = "HB1",         DestinationSubscriber = "HB2",         SentOrReceived = sent,         Message = message     };      var messages = new List<NcsMessage>();     messages.Add(msg);      Console.WriteLine("DelayDelivery: {0}", DateTime.Now);     Thread.Sleep(delay);     Console.WriteLine("DelayDelivery: {0}", DateTime.Now);      return messages; } 

I'm using Moq as the mocking framework and MSTest as the testing framework. Whenever I run the unit test, I get the following output:

DelayDelivery: 04/04/2013 15:50:33 DelayDelivery: 04/04/2013 15:50:36 VerifyMessage(Start): 04/04/2013 15:50:36 - 3000 VerifyMessage(Success): 04/04/2013 15:50:38 

Beyond the obvious "code smell" using the Thread.Sleep in the methods above, the result of the unit test is not what I'm trying to accomplish.

Can anyone suggest a better/accurate way to use the Moq framework to simulate a delay in "delivery" of the message. I've left out some of the "glue" code and only included the relevant parts. Let me know if something I've left out that prevents you from being able to understand the question.

like image 871
Julian Easterling Avatar asked Apr 04 '13 20:04

Julian Easterling


People also ask

Why do we use Moq in unit testing?

It is used in unit testing to isolate your class under test from its dependencies and ensure that the proper methods on the dependent objects are being called.

Can we mock static methods using Moq?

You can use Moq to mock non-static methods but it cannot be used to mock static methods.

Can we use Moq with NUnit?

We will install NUnit and Moq using the Nuget package manager. Make sure that in your references, NUnit and Moq are present after installation: For running NUnit tests and exploring the tests, we need to install a visual studio extension called “NUnit 3 Test Adapter”.

What is mock Moq?

Moq is a mocking framework built to facilitate the testing of components with dependencies. As shown earlier, dealing with dependencies could be cumbersome because it requires the creation of test doubles like fakes. Moq makes the creation of fakes redundant by using dynamically generated types.


1 Answers

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.

like image 91
Adam Rodger Avatar answered Oct 07 '22 07:10

Adam Rodger