Ihre Frage bezog sich darauf, wie sich das MS Fakes-Framework von NMock unterscheidet, und es scheint, dass die anderen Antworten einige davon gelöst haben. Hier finden Sie jedoch weitere Informationen dazu, wie sie gleich und wie unterschiedlich sie sind. NMock ähnelt auch RhinoMocks und Moq, daher gruppiere ich sie mit NMock.
Es gibt drei Hauptunterschiede zwischen NMock / RhinoMocks / Moq und dem MS Fakes Framework:
Das MS Fakes Framework verwendet generierten Code, ähnlich wie Accessors in früheren Versionen von Visual Studio anstelle von generischen Typen. Wenn Sie das Fakes-Framework für eine Abhängigkeit verwenden möchten, fügen Sie die Assembly, die die Abhängigkeit enthält, zu den Referenzen des Testprojekts hinzu und klicken Sie mit der rechten Maustaste darauf, um die Test-Doubles (Stubs oder Shims) zu generieren. Wenn Sie dann testen, verwenden Sie stattdessen tatsächlich diese generierten Klassen. NMock verwendet Generika, um dasselbe zu erreichen (dh IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
). Meiner Meinung nach verhindert der MS Fakes-Framework-Ansatz die Code-Navigation und das Refactoring innerhalb der Tests, da Sie tatsächlich gegen eine generierte Klasse arbeiten, nicht gegen Ihre eigentliche Schnittstelle.
Das MS Fakes Framework liefert Stubs und Moles (Shims), während NMock, RhinoMocks und Moq Stubs und Mocks liefern . Ich verstehe die Entscheidung von MS, keine Verspottungen aufzunehmen, wirklich nicht und bin persönlich aus den unten beschriebenen Gründen kein Fan von Maulwürfen.
Mit dem MS Fakes Framework bieten Sie eine alternative Implementierung der Methoden, die Sie stubben möchten. In diesen alternativen Implementierungen können Sie die Rückgabewerte angeben und Informationen darüber verfolgen, wie oder ob die Methode aufgerufen wurde. Mit NMock, RhinoMocks und Moq generieren Sie ein Scheinobjekt und verwenden dieses Objekt dann, um Stubbed-Rückgabewerte anzugeben oder Interaktionen zu verfolgen (ob und wie die Methoden aufgerufen wurden). Ich finde den Ansatz von MS-Fälschungen komplexer und weniger ausdrucksstark.
Um den Unterschied in den Frameworks zu verdeutlichen: NMock, RhinoMocks und Moq bieten zwei Arten von Test-Doubles (Stubs und Mocks). Das Fakes-Framework bietet Stubs und Moles (sie nennen sie Shims) und enthält leider keine Mocks. Um die Unterschiede und Ähnlichkeiten zwischen NMock und MS Fakes zu verstehen, ist es hilfreich zu verstehen, was diese verschiedenen Arten von Testdoppeln sind:
Stubs: Stubs werden verwendet, wenn Sie Werte für Methoden oder Eigenschaften angeben müssen, die von der zu testenden Methode von Ihrem Testdoppel verlangt werden. Wenn meine zu testende Methode beispielsweise die DoesStudentExist () -Methode des IStudentRepository-Testdoppels aufruft, möchte ich, dass sie true zurückgibt.
Die Idee von Stubs in NMock- und MS-Fälschungen ist dieselbe, aber mit NMock würden Sie so etwas tun:
Stub.On(mockStudentRepository).Method("DoesStudentExist").Will(Return.Value(true));
Und mit MSFakes würden Sie so etwas tun:
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
DoesStudentExistInt32 = (studentId) => { return new Student(); }
};
Beachten Sie, dass Sie im MS Fakes-Beispiel eine völlig neue Implementierung für die DoesStudentExist-Methode erstellen (Beachten Sie, dass sie DoesStudentExistInt32 heißt, da das Fakes-Framework die Parameterdatentypen an die Methodennamen anfügt, wenn es die Stub-Objekte generiert. Ich denke, dies beeinträchtigt die Klarheit von Die Tests). Um ehrlich zu sein, nervt mich die NMock-Implementierung auch, weil sie eine Zeichenfolge verwendet, um den Methodennamen zu identifizieren. (Verzeihen Sie mir, wenn ich falsch verstanden habe, wie NMock verwendet werden soll.) Dieser Ansatz hemmt das Refactoring wirklich und ich würde RhinoMocks oder Moq NMock aus diesem Grund wärmstens empfehlen.
Mocks: Mocks werden verwendet, um die Interaktion zwischen Ihrer zu testenden Methode und ihren Abhängigkeiten zu überprüfen. Mit NMock tun Sie dies, indem Sie ähnliche Erwartungen festlegen:
Expect.Once.On(mockStudentRepository).Method("Find").With(123);
Dies ist ein weiterer Grund, warum ich RhinoMocks und Moq NMock vorziehen würde. NMock verwendet den älteren Erwartungsstil, während RhinoMocks und Moq beide den Arrange / Act / Assert-Ansatz unterstützen, bei dem Sie Ihre erwarteten Interaktionen als Zusicherungen am Ende des Tests wie diesen angeben ::
stubStudentRepository.AssertWasCalled( x => x.Find(123));
Beachten Sie erneut, dass RhinoMocks ein Lambda anstelle einer Zeichenfolge verwendet, um die Methode zu identifizieren. Das ms fakes-Framework bietet überhaupt keine Mocks. Dies bedeutet, dass Sie in Ihren ausgeblendeten Implementierungen (siehe Beschreibung der Stubs oben) Variablen festlegen müssen, die Sie später überprüfen, ob sie korrekt festgelegt wurden. Das würde ungefähr so aussehen:
bool wasFindCalled = false;
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository()
{
DoesStudentExistInt32 = (studentId) =>
{
wasFindCalled = true;
return new Student();
}
};
classUnderTest.MethodUnderTest();
Assert.IsTrue(wasFindCalled);
Ich finde diesen Ansatz etwas verworren, da Sie den Anruf im Stub verfolgen und später im Test bestätigen müssen. Ich finde die Beispiele für NMock und insbesondere für RhinoMocks ausdrucksstärker.
Maulwürfe (Shims): Um ehrlich zu sein, ich mag Maulwürfe nicht, weil sie möglicherweise missbraucht werden. Eines der Dinge, die ich an Unit-Tests (und insbesondere an TDD) so sehr mag, ist, dass das Testen Ihres Codes Ihnen hilft, zu verstehen, wo Sie schlechten Code geschrieben haben. Dies liegt daran, dass das Testen von schlecht geschriebenem Code schwierig ist. Dies gilt nicht für die Verwendung von Maulwürfen, da Maulwürfe tatsächlich so konzipiert sind, dass Sie gegen nicht injizierte Abhängigkeiten testen oder private Methoden testen können. Sie funktionieren ähnlich wie Stubs, außer dass Sie einen ShimsContext wie folgt verwenden:
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}
Meine Sorge bei Unterlegscheiben ist, dass die Leute sie als "einfacheren Weg zum Unit-Test" ansehen, weil Sie dadurch nicht gezwungen werden, Code so zu schreiben, wie Sie es sollten. Eine ausführlichere Beschreibung dieses Konzepts finden Sie in meinem Beitrag:
Weitere Informationen zu einigen Bedenken im Zusammenhang mit den gefälschten Frameworks finden Sie in den folgenden Beiträgen:
Wenn Sie RhinoMocks lernen möchten, finden Sie hier ein Pluralsight-Schulungsvideo (vollständige Offenlegung - Ich habe diesen Kurs geschrieben und bekomme Lizenzgebühren für Ansichten, aber ich denke, dass dies für diese Diskussion gilt, also füge ich ihn hier ein):