2013-04-04 9 views
8

Ich versuche folgendes zu prüfen:Simulieren eine Verzögerung bei der Ausführung in Unit-Test unter Verwendung Moq

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

mit dem folgenden 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() gibt nur eine Reihe von Zeichen und das „Delay Delivery“ Methode ist

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

ich Moq als Mockframework und MSTest als testin bin mit g Rahmen. Jedes Mal, wenn ich das Gerät Test ausführen, ich folgende Ausgabe:

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 

über den Tellerrand hinaus „Codegeruch“ über die Thread.Sleep in den Verfahren verwendet wird, ist das Ergebnis des Unit-Tests nicht, was ich versuche erreichen.

Kann jemand vorschlagen eine bessere/genaue Möglichkeit, das Moq-Framework zu verwenden, um eine Verzögerung in "Lieferung" der Nachricht zu simulieren. Ich habe etwas vom "Kleber" -Code weggelassen und nur die relevanten Teile eingeschlossen. Lassen Sie mich wissen, wenn etwas, das ich weggelassen habe, Sie daran hindert, die Frage zu verstehen.

+3

Sie wäre besser dran, ein Beispiel zu erstellen jemand (anders als Sie) kann tatsächlich, dass Highlights, was Sie versuchen, zu erreichen. Es gibt hier nichts, was jemand kopieren und laufen könnte, ohne eine Menge zusätzlicher Arbeit zu leisten. –

Antwort

27

Wenn Sie eine Moq Mock wollen für ein Nichts, einfach nur sitzen und tun, während Sie einen Rückruf verwenden:

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

Ich habe versucht, dass in LinqPad und wenn Sie die Thread.Sleep() die Ausführungszeit einstellen variiert entsprechend .

+0

Die Callback() -Methode war, was mir fehlte ... Ich habe den Komponententest aktualisiert, um diesen zu verwenden, und der Komponententest "verspottet" die Verzögerung jetzt richtig ... Danke! –

+4

das scheint nicht für mich zu arbeiten, ich denke, der Rückruf wird ausgeführt, nachdem das Ergebnis von der Moq zurückgegeben wird –

+0

Ich stimme mit @DanDinu - wenn Sie zwei gleichzeitige Aufrufe von 'Bar()' dann die beiden 'Callback' s werden ausgeführt * nachdem * beide 'Bar()' s abgeschlossen sind. – OffHeGoes

0

Ich konnte nicht bekommen Moq Version zu arbeiten, so dass ich am Ende so etwas wie dies zu machen:

ein kleines Beispiel mit 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(); 

    } 

} 
6

Wenn Sie Setup Ihre mock Sie den Thread sagen kann Schlaf in der Rückkehr func:

Verwandte Themen