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):
Sie haben Recht, aber die Geschichte enthält noch mehr. Die wichtigsten Dinge, die Sie aus dieser Antwort herausnehmen sollten, sind:
Ihre Architektur sollte Stubs und Abhängigkeitsinjektion richtig nutzen, anstatt sich auf die Krücke von Fakes und Mocks zu verlassen
Fälschungen und Verspottungen sind nützlich, um Code zu testen, den Sie nicht ändern sollten oder können, z.
Shims (während der Entwicklung als "Maulwürfe" bekannt) sind in der Tat ein spöttisches Framework, das als Umleitung von Anrufen dient. Anstatt akribisch ein Modell zu erstellen (ja, selbst die Verwendung von Moq ist relativ schmerzhaft!), Verwenden Shims einfach das bereits vorhandene Produktionscode-Objekt. Shims leiten den Anruf einfach vom Produktionsziel an den Testdelegierten weiter.
Stubs werden aus Schnittstellen im Zielprojekt generiert. Das Stub-Objekt ist genau das - eine Implementierung der Schnittstelle. Der Vorteil der Verwendung des Stub-Typs besteht darin, dass Sie schnell einen Stub generieren können, ohne Ihr Testprojekt mit vielen Stubs zur einmaligen Verwendung zu überladen, ganz zu schweigen von der Zeitverschwendung beim Erstellen. Natürlich sollten Sie immer noch konkrete Stichleitungen erstellen, die für viele Tests verwendet werden können.
Die effiziente Implementierung von Fakes (Shims, Mocks und Stub-Typen) ist etwas gewöhnungsbedürftig, aber die Mühe lohnt sich. Ich persönlich habe durch die Verwendung der Typen Shims / Mole, Mocks und Stub Wochen Entwicklungszeit gespart. Ich hoffe, Sie haben genauso viel Spaß mit der Technologie wie ich!
quelle
So wie ich es verstehe, wollte das Visual Studio-Team vermeiden, mit den verschiedenen für .NET verfügbaren Scheinbibliotheken zu konkurrieren. MS steht oft vor solchen schwierigen Entscheidungen. Sie sind aufgestaut, wenn sie bestimmte Funktionen nicht bereitstellen ("Warum stellt MS uns keine Scheinbibliothek zur Verfügung; Verspottungen sind eine so häufige Anforderung?") Und verdammt, wenn sie dies tun ("Warum handelt Microsoft so aggressiv und treibt seine an) natürliche Unterstützer aus dem Markt? ") Sehr oft, aber nicht immer, beschließen sie, sich zurückzuhalten, einfach ihre eigene Alternative zu verfügbaren und gut aufgenommenen Technologien anzubieten. Das scheint hier der Fall zu sein.
Die Shim-Funktion von Fakes ist wirklich sehr, sehr nützlich. Klar, es gibt Gefahren. Es erfordert etwas Disziplin, um sicherzustellen, dass Sie dies nur bei Bedarf verwenden. Es füllt jedoch eine große Lücke. Meine Hauptbeschwerde ist, dass es nur mit der Ultimate Edition von VS 2012 geliefert wird und daher nur einem Unterabschnitt der .NET-Entwicklergemeinschaft zur Verfügung steht. Was für eine Schande.
quelle
Fakes enthält zwei verschiedene Arten von "gefälschten" Objekten. Der erste, der als "Stub" bezeichnet wird, ist im Wesentlichen ein automatisch generierter Dummy, dessen Standardverhalten überschrieben werden kann (und normalerweise würde), um ihn zu einem interessanteren Mock zu machen. Es fehlen jedoch einige der Funktionen, die die meisten derzeit verfügbaren Mocking-Frameworks bieten. Wenn Sie beispielsweise überprüfen möchten, ob eine Methode für eine Stub-Instanz aufgerufen wurde, müssen Sie die Logik dafür selbst hinzufügen. Wenn Sie Ihre eigenen Mocks jetzt manuell erstellen, scheinen Stubs im Grunde genommen eine Verbesserung zu sein. Wenn Sie jedoch bereits ein umfassenderes Mocking-Framework verwenden, haben Sie möglicherweise das Gefühl, dass einige wichtige Teile in Fakes-Stubs fehlen.
Die andere von Fakes angebotene Objektkategorie, die als "Shim" bezeichnet wird, stellt einen Mechanismus zum Ersetzen des Verhaltens von Abhängigkeiten bereit, die für den Standardersatz über Mocks nicht angemessen entkoppelt wurden (oder nicht entkoppelt werden können). AFAIK, TypeMock ist das einzige der wichtigsten Verspottungs-Frameworks, das derzeit diese Art von Funktionalität bietet.
Übrigens, wenn Sie Moles schon einmal ausprobiert haben, ist Fakes im Wesentlichen dasselbe und findet schließlich seinen Weg aus Microsoft Research in ein tatsächliches Produkt.
quelle
In Bezug auf gefälschte (Shim + Stub) Objekte wurde es oben gut definiert, obwohl ich denke, dass der letzte Absatz im letzten Kommentar die gesamte Situation ziemlich gut zusammenfasst.
Obwohl viele Leute argumentieren werden, dass gefälschte (Shim + Stub) Objekte in einigen Unit-Test-Fällen ein gutes Gut sind, ist der Nachteil, dass diese Optionen NUR verfügbar sind, egal ob Sie Visual Studio 2012 oder Visual Studio 2013 verwenden mit Premium- oder Ultimate-Versionen. IOW, dies bedeutet, dass Sie KEINE dieser Fälschungen (Shim + Stub) auf einer Pro-Version ausführen dürfen.
Möglicherweise wird die Menüoption "Fälschungen" (Shim + Stub) in Pro-Versionen angezeigt, aber Vorsicht, es besteht eine ziemlich hohe Wahrscheinlichkeit, dass Sie am Ende absolut nichts haben ... Es wird kein Kompilierungsfehler generiert, der Ihnen sagt, dass etwas Wichtiges vorliegt fehlt, Optionen sind einfach nicht da, also verschwenden Sie nicht Ihre Zeit ...
Dies ist ein wichtiger Faktor, der in einem Entwicklerteam berücksichtigt werden muss, insbesondere wenn einer der einzigen ist, der die Ultimate-Version verwendet, während alle anderen die Pro-Version verwenden. Moq hingegen kann problemlos über Nuget installiert werden, unabhängig davon, welche Visual Studio-Version Sie verwenden. Ich hatte kein Problem mit Moq, der Schlüssel bei jedem Tool ist zu wissen, wofür sie verwendet werden und wie man sie richtig verwendet;)
quelle