2010-07-17 8 views
107

diese Klasse StellenMoq: Wie ein Parameter ein Verfahren zur Herstellung eines verspotteten Dienstes übergeben bekommen

public class Foo { 

    private Handler _h; 

    public Foo(Handler h) 
    { 
     _h = h; 
    } 

    public void Bar(int i) 
    { 
     _h.AsyncHandle(CalcOn(i)); 
    } 

    private SomeResponse CalcOn(int i) 
    { 
     ...; 
    } 
} 

Mo (q) cking Handler in einem Test von Foo, wie würde ich in der Lage sein, was zu überprüfen Bar() ist an _h.AsyncHandle weitergegeben?

+0

Meinten Sie "AsyncHandle" (extra "n")? Und könnten Sie den Code für Handler eingeben oder den vollständig qualifizierten Typnamen angeben, wenn es sich um einen Standardtyp handelt? – TrueWill

+0

Kannst du deinen Skeletttest zeigen, um zu zeigen, was du denkst? Während ich weiß, dass es von Ihrer Seite her offensichtlich ist, sieht es von unserer Seite aus so aus, als hätte sich jemand die Zeit genommen, die Frage zu beantworten, ohne eine lange spekulative Antwort zu geben. –

+1

Es gibt weder einen Foo noch einen Bar() noch irgendetwas ähnliches. Es ist nur ein Demo-Code, um die Situation zu zeigen, in der ich mich befinde, ohne mich von Anwendungsspezifikationen abzulenken. Und ich bekam nur die Antwort, ich hoffte zu bekommen. – Jan

Antwort

178

Sie können das Mock.Callback-Methode:

var mock = new Mock<Handler>(); 
SomeResponse result = null; 
mock.Setup(h => h.AnsyncHandle(It.IsAny<SomeResponse>())) 
    .Callback<SomeResponse>(r => result = r); 

// do your test 
new Foo(mock.Object).Bar(22); 
Assert.NotNull(result); 

Wenn Sie nur in Argument etwas einfach auf die bestandene überprüfen möchten, können Sie es auch direkt tun:

mock.Setup(h => h.AnsyncHandle(It.Is<SomeResponse>(response => response != null))); 
+1

perfekt, danke! – Jan

+14

Eine Randnotiz, wenn Sie mehrere Argumente für Ihre Funktion haben, müssen Sie alle Typen in der generischen 'Callback <>()' Moq Methode angeben. Wenn Sie zum Beispiel die Definition 'Handler.AnsyncHandle (string, SomeResponse)' hätten, müssten Sie '/ * ... * /. Callback (r => result = r);'. Ich habe das an vielen Stellen nicht ausdrücklich erwähnt, daher dachte ich, ich würde es hier hinzufügen. –

17

Gamlor des Antwort funktioniert, aber eine andere Art es zu tun (und eine, die ich im Test als expressiver erachte) ist ...

Verify ist sehr leistungsfähig und es lohnt sich, sich die Zeit zu nehmen, sich daran zu gewöhnen.

+9

Dieser Ansatz ist in Ordnung, wenn Sie nur überprüfen möchten, ob eine Methode mit einem bekannten Parameter aufgerufen wurde. In dem Fall, in dem der Parameter zum Zeitpunkt des Schreibens des Tests noch nicht erstellt wurde (z. B. erstellt die betreffende Einheit den Parameter intern), ermöglicht Callback Ihnen, dies zu erfassen und abzufragen, während Ihr Ansatz dies nicht tun würde. – Michael

+0

Ich muss den übergebenen Wert speichern, da ich überprüfen muss, ob alle Objekte übergeben wurden. – MrFox

1

Sie könnten It.Is<TValue>() Matcher verwenden.

var mock = new Mock<Handler>(); new Foo(mock.Object).Bar(22); mock.Verify(h => h.AsyncHandle(It.Is<SomeResponse>(r => r != null)));

+0

Typo - 'AnsyncHandle' sollte 'AsyncHandle' sein –

2

Gamlor Antwort war für mich, aber ich dachte, dass ich auf John Carpenters Kommentar erweitern würde, weil ich nach einer Lösung suchen, um mehr als einen Parameter beteiligt sind. Ich denke, dass andere Leute, die auf diese Seite stolpern, sich in einer ähnlichen Situation befinden. Ich habe diese Information in der Moq documentation gefunden.

Ich werde Gamlor's Beispiel verwenden, aber täuschen wir vor, dass die AsyncHandle-Methode zwei Argumente benötigt: ein string und ein SomeResponse Objekt.

var mock = new Mock<Handler>(); 
string stringResult = string.Empty; 
SomeResponse someResponse = null; 
mock.Setup(h => h.AsyncHandle(It.IsAny<string>(), It.IsAny<SomeResponse>())) 
    .Callback<string, SomeResponse>((s, r) => 
    { 
     stringResult = s; 
     someResponse = r; 
    }); 

// do your test 
new Foo(mock.Object).Bar(22); 
Assert.AreEqual("expected string", stringResult); 
Assert.IsNotNull(someResponse); 

Grundsätzlich brauchen Sie nur eine weitere It.IsAny<>() mit dem entsprechenden Typ hinzuzufügen, einen anderen Typ der Callback Methode hinzufügen, und die Lambda-Ausdruck entsprechend zu ändern.

Verwandte Themen