2009-06-12 7 views
6

Ich spotte einen Wrapper zu einem MSMQ. Der Wrapper ermöglicht es einfach, eine Objektinstanz zu erstellen, die statische Methoden der MessageQueue-Klasse aufruft.Kann ich eine Reihe von guten Ergebnissen und eine geworfene Ausnahme von Moq erhalten

Ich möchte testen, die Warteschlange bis zur Erschöpfung zu lesen. Um dies zu tun, möchte ich, dass der verspottete Wrapper einige gute Ergebnisse zurückgibt und beim vierten Aufruf der gleichen Methode eine Ausnahme auslöst. Die Methode akzeptiert keine Parameter und gibt ein Standardnachrichtenobjekt zurück.

Kann ich diese Reihe von Erwartungen auf die Methode in Moq einrichten?

+0

+1 Da Moq genial ;-) ist mir davon erzählen – toxvaerd

+0

! Seit über einem Jahr habe ich ein bestimmtes kommerzielles Produkt benutzt, dessen Name hier nicht erwähnt werden soll und ich HASTE spöttisch. Ich musste die Dokumentation ständig lesen und neu lesen. Moq ist so ein Hauch frischer Luft. Ich konnte es in ein paar Minuten verwenden und brauche selten die Dokumentation zu lesen. –

+0

Ich habe RhinoMocks benutzt, aber ich dachte, ich würde Moq einen Besuch abstatten, um zu sehen, wie es sich vergleicht und mein Wissen verbreitet. Ich bin jetzt ein Convert - ich finde Moq Syntax beim Scannen von Code leichter zu lesen. – BlackWasp

Antwort

5

Ja, das ist möglich, wenn es dir nichts ausmacht, durch ein paar kleine Reifen zu springen. Ich habe das schon einmal für eines meiner Projekte getan. Okay, hier ist die Grundtechnik. Getestet habe ich es gerade aus in Visual Studio 2008, und das funktioniert:

var mockMessage1 = new Mock<IMessage>(); 
var mockMessage2 = new Mock<IMessage>(); 
var mockMessage3 = new Mock<IMessage>(); 

var messageQueue = new Queue<IMessage>(new [] { mockMessage1.Object, mockMessage2.Object, mockMessage3.Object }); 

var mockMsmqWrapper = new Mock<IMsmqWrapper>(); 

mockMsmqWrapper.Setup(x => x.GetMessage()).Returns(() => messageQueue.Dequeue()).Callback(() => 
{ 
    if (messageQueue.Count == 0) 
     mockMsmqWrapper.Setup(x => x.GetMessage()).Throws<MyCustomException>(); 
}); 

Ein paar Anmerkungen:

  1. Sie müssen sich nicht spotten Nachrichten zurückzukehren, aber es ist sinnvoll, wenn Sie möchten, Erwartungen überprüfen auf jeder Nachricht, um zu sehen, ob bestimmte Methoden aufgerufen oder Eigenschaften festgelegt wurden.
  2. Die Warteschlangen-Idee ist nicht meine eigene, nur ein Tipp, den ich von einem Blogpost bekommen habe.
  3. Der Grund, warum ich eine Ausnahme von MyCustomException werfe, liegt daran, dass die Queue-Klasse automatisch eine InvalidOperationException auslöst. Ich wollte sicherstellen, dass das verspottete MsmqWrapper-Objekt wegen Moq eine Ausnahme auslöst und nicht, weil die Warteschlange keine Elemente mehr enthält.

Hier ist der vollständige Code, der funktioniert. Beachten Sie, dass dieser Code an einigen Stellen ist hässlich, aber ich wollte Ihnen nur zeigen, wie diese getestet werden konnte:

public interface IMsmqWrapper 
{ 
    IMessage GetMessage(); 
} 

public class MsmqWrapper : IMsmqWrapper 
{ 
    public IMessage GetMessage() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class Processor 
{ 
    private IMsmqWrapper _wrapper; 
    public int MessagesProcessed { get; set; } 
    public bool ExceptionThrown { get; set; } 

    public Processor(IMsmqWrapper msmqWrapper) 
    { 
     _wrapper = msmqWrapper;   
    } 

    public virtual void ProcessMessages() 
    { 
     _wrapper.GetMessage(); 
     MessagesProcessed++; 
     _wrapper.GetMessage(); 
     MessagesProcessed++; 
     _wrapper.GetMessage(); 
     MessagesProcessed++; 

     try 
     { 
      _wrapper.GetMessage(); 
     } 
     catch (MyCustomException) 
     { 
      ExceptionThrown = true; 
     } 
    } 
} 

[Test] 
public void TestMessageQueueGetsExhausted() 
{ 
    var mockMessage1 = new Mock<IMessage>(); 
    var mockMessage2 = new Mock<IMessage>(); 
    var mockMessage3 = new Mock<IMessage>(); 

    var messageQueue = new Queue<IMessage>(new [] { mockMessage1.Object, mockMessage2.Object, mockMessage3.Object }); 

    var mockMsmqWrapper = new Mock<IMsmqWrapper>(); 
    mockMsmqWrapper.Setup(x => x.GetMessage()).Returns(() => messageQueue.Dequeue()).Callback(() => 
    { 
     if (messageQueue.Count == 0) 
      mockMsmqWrapper.Setup(x => x.GetMessage()).Throws<InvalidProgramException>(); 
    }); 

    var processor = new Processor(mockMsmqWrapper.Object); 

    processor.ProcessMessages(); 

    Assert.That(processor.MessagesProcessed, Is.EqualTo(3)); 
    Assert.That(processor.ExceptionThrown, Is.EqualTo(true)); 
} 
Verwandte Themen