Ist es empfehlenswert, konkrete Klasse zu verspotten?
Meisten der Beispiele in den mocking framework website-mock-Schnittstelle. Lassen Sie sagen, NSubstitute, ich bin derzeit mit, all Ihr Spott Beispiele zu mock-Schnittstelle.
Aber in der Realität, ich sah einige Entwickler mock konkrete Klasse statt. Ist es empfehlenswert, zu verspotten konkrete Klasse?
InformationsquelleAutor der Frage DonDon | 2012-08-29
Du musst angemeldet sein, um einen Kommentar abzugeben.
In der Theorie gibt es absolut kein problem die Verspottung einer konkreten Klasse; wir testen gegen eine logische Schnittstelle (eher als eine keyword -
interface
), und es spielt keine Rolle, ob das logische Schnittstelle wird durch einclass
oderinterface
.In der Praxis .NET/C# macht das ein bisschen problematisch. Wie Sie bereits erwähnt ein .NET framework imitieren ich nehme an, Sie sind eingeschränkt.
In .NET/C# - Mitglieder sind nicht-virtuelle standardmäßig, so dass jeder proxy-basierte Methoden der Spott Verhalten (d.h. die Ableitung von der Klasse und überschreiben alle Mitglieder zu tun, test-spezifische Sachen) wird nicht funktionieren, es sei denn, Sie explizit zu markieren, die Mitglieder als
virtual
. Dies führt zu einem problem: Sie verwenden eine Instanz der Klasse verspottet, die bedeutete, zu sein, vollständig sicher in Ihrem unit-test (d.h. nicht ausgeführt alle richtigen code), aber es sei denn, Sie haben Sie sicher, alles istvirtual
Sie können am Ende mit eine Mischung aus real-und verspottet-code ausgeführt werden (dies kann besonders problematisch sein, wenn es Konstruktor-Logik, die immer läuft, und wird noch verschärft, wenn es andere konkrete Abhängigkeiten zu neuer würde).Gibt es ein paar Möglichkeiten, dies zu umgehen.
interfaces
. Das funktioniert und ist das, was wir beraten in der NSubstitute Dokumentationhat aber den Nachteil der potentiell Blähungen Ihre Codebasis mit Schnittstellen, die nicht wirklich benötigt werden. Wohl, wenn wir finden, gute Abstraktionen in unserem code, wir werden natürlich am Ende ordentlich mit, wiederverwendbare Schnittstellen, die wir testen können. Ich habe nicht ganz gesehen, es klappt so, aber YMMV. 🙂Einer gemeinsamen Beschwerde gegen die Letzte Idee ist, dass Sie die Prüfung über eine "fake" - Naht; wir werden nach draußen gehen, die Mechanismen, die normalerweise für die Erweiterung code zu ändern, das Verhalten von unserem code. Brauchen nach draußen zu gehen, diese Mechanismen könnten darauf hinweisen, Steifigkeit in unserem design. Ich verstehe das argument, aber ich habe Fälle gesehen, wo der Lärm der Schaffung einer anderen Schnittstelle/s überwiegt die Vorteile. Ich denke, es ist eine Frage des seins bewusst, die potenziellen design-Problem, wenn Sie nicht müssen, dass das feedback aus den tests zu markieren design Steifigkeit, dann können Sie großartige Lösungen.
Eine Letzte Idee, ich werde werfen, dort ist zu spielen, um mit der änderung der Größe der Einheiten, die in unseren tests. In der Regel haben wir eine einzelne Klasse als Einheit. Wenn wir eine Reihe von zusammenhängenden Klassen, als unsere Einheit, und haben Schnittstellen als eine gut definierte Grenze, um diese Komponente, dann können wir vermeiden, dass Sie zu verspotten, wie viele Klassen und stattdessen nur Modell über eine stabilere Grenze. Diese können, machen Sie unsere tests ein komplizierteres, mit dem Vorteil, dass wir testen gerade eine geschlossene Einheit von Funktionalität und ermutigt zur Entwicklung solider Schnittstellen rund um das Gerät.
Hoffe, das hilft.
InformationsquelleAutor der Antwort David Tchepak
Update:
3 Jahre später will ich zugeben, dass ich meine Meinung geändert.
Schon in der Theorie weiß ich noch nicht wie das erstellen Schnittstellen, die nur zur Erleichterung der Erstellung von mock-Objekten in der Praxis ( ich bin mit NSubstitute) es ist viel einfacher zu bedienen
Substitute.For<MyInterface>()
eher als mock echt Klasse mit mehreren Parametern, z.B.Substitute.For<MyCLass>(mockedParam1, mockedParam2, mockedParam3)
wo die einzelnen parameter werden sollte, verspottet getrennt. Andere potenzielle Probleme beschrieben, die in NSubstitute DokumentationIn unserer Firma die empfohlene Praxis, nun ist Schnittstellen verwenden.
Ursprüngliche Antwort:
Wenn Sie nicht haben eine Anforderung zu erstellen, die mehrere Implementierungen der gleichen Abstraktion, nicht eine Schnittstelle erstellen.
Wie es Spitzen von David Tchepak, wollen Sie nicht zu Blähungen Ihr Codebasis mit Schnittstellen, die nicht wirklich benötigt werden.
Vom http://blog.ploeh.dk/2010/12/02/InterfacesAreNotAbstractions.aspx
Wenn Ihr Ziel ist, die Testbarkeit, die ich bevorzuge, die zweite option aus David Tchepak Antwort oben.
Aber ich bin nicht davon überzeugt, dass Sie alles virtuell. Es ist ausreichend, um die virtuellen nur die Methoden, die Sie gehen zu ersetzen.
Ich werde auch einen Kommentar hinzufügen neben der Deklaration der Methode, die Methode virtuell ist nur zu machen, auswechselbarer für unit-test, mocking.
Jedoch beachten, dass die substitution von konkreten Klassen statt interfaces. hat einige Einschränkungen.
E. g. für NSubstitute
.
InformationsquelleAutor der Antwort Michael Freidgeim
Die Frage ist eher: Warum nicht?
Ich denken kann ein paar Szenarien, wo dies nützlich ist, wie:
Umsetzung einer konkreten Klasse ist noch nicht abgeschlossen, oder der Typ der das gemacht hat, es ist unzuverlässig. Also ich verspotte die Klasse, wie es angegeben ist und mein test-code vor.
Kann es auch nützlich sein, um mock-Klassen, die Dinge tun, wie Datenbank-Zugriff. Wenn Sie nicht über eine test-Datenbank möchten Sie möglicherweise die Werte zurückgeben für deine tests, die sind immer konstant (das ist einfach durch Spott der Klasse).
InformationsquelleAutor der Antwort konqi