2010-02-19 10 views
10

Ich habe dieses Problem, die 3,5 um einen Fehler in Rhino Mocks sein kann:Rhino Mocks Überschreiben von Stubs möglich?

stubObj = MockRepository.GenerateStub(IObject); 

stubObj.Stub(a=>a.Get()).Return (Guid.Empty); //1.stub 
stubObj.Stub(a=>a.Get()).Return (Guid.NewGuid()); //2.stub, should overwrite the first one? 

dies:

var value = stubObj.Get(); 

kehrt Guid.Empty, dann ist dies das richtige Verhalten?

+0

Ich verstehe nicht ganz, warum Sie eine Erwartung ‚überschreiben‘ wollen. Das Verhalten scheint mir in Ordnung zu sein. Nur eine Spekulation von mir: Wenn Sie versuchen, einen Stub für eine andere Behauptung wiederzuverwenden oder zu recyceln, dann sollten Sie das nicht tun. Das wäre keine gute Übung, um Tests zu schreiben. –

Antwort

0

Die folgenden Tests sollten passieren:

// arrange 
var stubObj = MockRepository.GenerateStub<IObject>(); 
stubObj.Stub(a => a.Get()) 
     .Return(Guid.Empty); 
// act 
var value = stubObj.Get(); 
// assert 
Assert.AreEqual(Guid.Empty, value); 

Und wenn Sie eine neue GUID zurückgeben möchten:

// arrange 
var stubObj = MockRepository.GenerateStub<IObject>(); 
stubObj.Stub(a => a.Get()) 
     .Return(Guid.NewGuid()); 
// act 
var value = stubObj.Get(); 
// assert 
Assert.AreNotEqual(Guid.Empty, value); 
+0

danke, aber ich will es nicht noch einmal arrangieren, nur um Stub-Rückgabewert zu ändern. Gibt es eine Art von replay() -Methode, die nur das angegebene Stub-Objekt wiederholt? – David

1

Sie haben programmiert nur das Stub-Objekt für zwei getrennte Anrufe. Wenn Sie stubObj.Get erneut aufrufen, sollten Sie bekommen, was Guid.NewGuid erzeugt. Sie können Ihr gefälschtes Objekt für eine beliebige Anzahl von Aufrufen unterschiedlicher Art vorbereiten. Aus diesem Grund ist es nicht sinnvoll, zu erwarten, dass der letzte .Stub Aufruf für einen gegebenen Aufruf vorherige .Stub Bings dieses Aufrufs ersetzt.

In Ihrem Testcode, der kurz und ordentlich sein sollte, sollte es nie einen Fall geben, in dem Sie eine solche Programmierung des Mocks so rückgängig machen müssen, wie Sie es scheinbar tun möchten.

Wenn was zurückgegeben werden muss, ist eine bedingte Sache, die abhängig von anderen Bits Ihres Test-Codes über mehrere Aufrufe an diesen Block von Code, das letzte, was Sie wollen, ist magische passiert, damit die Leser herausfinden müssen, was Sie gemeint. Wenn es bedingt ist, sollten Sie es deutlich machen.

Und dann, wenn Sie es klar gemacht haben, es Refactoring, wie Sie nicht Bedingte Logik in Tests haben sollten (siehe xUnit Testmuster)

+0

ein Nitpick: 'Stub' setzt nur Verhalten, nicht Erwartungen.Es ist bedauerlich, dass RhinoMocks sowohl Record-Replay-Verify (wo Sie die Erwartungen aufzeichnen) als auch arrange-act-assert (wo Sie Stubs und separate Assertions verwenden würden) unterstützt, was die Erklärung sehr kompliziert macht. –

+0

@wcoenen: Ich benutze keine RhinoMocks, und der Grusel und die Verwirrung, die durch die verschiedenen Modelle und andere Legacy Cruft verursacht wird, ist der Hauptgrund (ich wähle Moq, da es eine Meinung hat). Die Hauptsache, die ich in meiner Antwort vermitteln wollte, war, dass Sie sich im Allgemeinen auf mehrere Anrufe vorbereiten, und daher würde es in den meisten Fällen überraschend sein, wenn das Framework alle auf einen zusammenfasst, wie es der Frager scheint vorschlagen würde Sinn machen). Ich freue mich, wenn jemand meine Terminologie überarbeitet und bearbeitet hat, um sie für RM-Benutzer weniger unübersichtlich zu machen. –

+0

@wcoenen: Ich habe versucht, den Missbrauch der RM-Terminologie zu entfernen, indem ich sie durch allgemeine Terminologie ersetze, und würde mich über zusätzliche Bearbeitungen freuen, um die Dinge weniger verwirrend zu gestalten. (Hat in den letzten Tagen Kapitel 6 oder PragProgs Unit Testing Buch [veröffentlicht 2007] gelesen, das RhinoMocks in eine Seitenleiste verbannt [und Moq nicht erwähnt], was bei der Terminologie nicht hilft. (Ich stehe immer noch über meinem Hauptpunkt, der das ist sollte nicht ein Stub/Mock-Setup als Teil eines Tests ändern oder anderweitig in einer solchen Conditional Logic In Test Anti-Patterns.) –

8

Wenn Sie die leere Guid eine bekannte Anzahl von Zeiten zurückkehren wollen Das einzige, was Sie tun müssen, ist RhinoMocks zu sagen, wie oft es wiederholt werden soll, z der folgende Test bestanden:

[Test] 
    public void MultipleStubsTest() 
    { 
     var testMock = MockRepository.GenerateMock<ITest>(); 
     testMock.Stub(x => x.Get()).Return(Guid.Empty).Repeat.Once(); 
     testMock.Stub(x => x.Get()).Return(Guid.NewGuid()); 

     Assert.AreEqual(Guid.Empty, testMock.Get()); 
     Assert.AreNotEqual(Guid.Empty, testMock.Get()); 
    } 

wenn Sie nicht wissen, wie oft Get() aufgerufen wird, bevor die guid ändern sollte, als Sie immer .DO verwenden können() und Code es dort (lassen Sie mich bitte wissen, ob Sie weitere Details benötigen).

+0

Ich würde ** liebe ** mehr Details darüber, wie ich 'Do()' if verwenden kann Ich weiß nicht, wie oft 'Get() 'aufgerufen wird. Ich kann' testMock' nicht durch einen neuen Schein ersetzen, also muss ich den Wert ändern, den 'Get()' zurückgibt. – smoksnes

+0

Nevermind die Antwort hier http://stackoverflow.com/questions/13918281/why-cant-i-change-the-return-value-in-a-rhino-mocks-stub-object – smoksnes

1

So würden Sie es tun. Es gibt meine Maschine weiter.

[TestMethod] 
    public void Test() 
    { 
     stubObj = MockRepository.GenerateMock<IGuidTest>(); 

     stubObj.Stub(a => a.Get()).Repeat.Times(1).Return(Guid.Empty); 
     stubObj.Stub(a => a.Get()).Repeat.Times(1).Return(Guid.NewGuid()); 

     Assert.AreEqual(Guid.Empty, stubObj.Get()); 
     Assert.AreNotEqual(Guid.Empty, stubObj.Get()); 

    } 
    public IGuidTest stubObj; 
    public interface IGuidTest 
    { 
     Guid Get(); 
    } 
-1

Ja, das ist das erwartete Verhalten. Wenn Sie die Erwartungen/Stubs auf diese Weise schreiben, wird das spöttische Framework angewiesen, Guid.Empty beim ersten Aufruf der Get() -Methode zurückzugeben und Guid.NewGuid() das zweite Mal, wenn es aufgerufen wird, zurückzugeben.

Hier sind ein paar Möglichkeiten, um die erste Erwartung mit dem zweiten „überschreiben“: How to change behaviour of stubs?

+0

NO, ohne .Repeat.Once Option , Stub gibt nur den ersten Stub zurück (leer) und niemals den zweiten (neu). –