Umsetzung von mocking-Objekte mit Moq, wenn Konstruktor-Parameter
Habe ich gelesen, das Antwort von Ragzitsu für die gleiche Frage. Ich bin immer noch verwirrt, wie man implementieren Sie die Dinge aber. Kann jemand mir ein Beispiel für eine Implementierung.
Habe ich die folgenden Klassen:
class Fizz : IFizz
{
}
class Buzz : IBuzz
{
}
class Bar : IBar
{
}
class Foo : IFoo
{
public Foo(IBar bar, IFizz fizz, IBuzz buzz)
{
//initialize etc.
}
//public methods
}
Was ist der praktische Weg, um rund um den Konstruktor hier? Ich will etwas tun, wie
var foo = new Mock<IFoo>();
In anderen Worten, wie würde der code Aussehen nach der Beratung
The best thing to do would be right click on your class and choose Extract interface.
Ich verstehe nicht, was Sie hier zu tun versuchen? Können Sie das erklären?
Interesse bei der Auswahl einer Lösung für dieses? Wenn es noch Verwirrung, bitte um Klarheit über Kommentare.
Interesse bei der Auswahl einer Lösung für dieses? Wenn es noch Verwirrung, bitte um Klarheit über Kommentare.
InformationsquelleAutor happygilmore | 2013-12-22
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie erstellen mock, wo Konstruktor hat param Argumente mit Verweis MockBehavior, siehe unten
InformationsquelleAutor Ashraf Alam
Werde ich die Adresse dieses Konzept in einer orthogonalen Sinn. Ich bin nicht einverstanden mit dieser Aussage, eine Schnittstelle ist nicht die Lösung, um die Situation in Frage stellen.
Gehen wir zurück zu der vorherigen Frage text:
Beachten Sie die Methode, die ich Hinzugefügt.
Ich glaube, die wirkliche Frage ist, wenn Sie nicht speziell testen
CustomerSyncEngine
sondern testet die Klasse, die hängt aufCustomerSyncEngine
. Nennen wir diese KlasseSuperSyncEngine
. Erstellen Sie einen test gegenSuperSyncEngine
wird ein Schmerz sein, da Sie zu verspotten, die für die gesamteCustomerSyncEngine
mit seiner 3-Schnittstellen, zusammen mit anderen zusätzlichen AbhängigkeitenSuperSyncEngine
hat.Gegeben, dass der code, die Sie suchen, um zu testen, ist
SuperSyncEngine
hängtCustomerSyncEngine
eine Schnittstelle ist nicht die Antwort hier. Sie könnte erstellenICustomerSyncEngine
aber das interface sollte nicht erstellt werden, lediglich für ein mocking-framework. Die bessere Lösung ist, zu ändernCustomerSyncEngine.MethodWithDependencies
werden virtuellenDies würde ermöglichen es Ihnen, ersetzen Sie die Methode mit einem mocking framework das ignorieren der Abhängigkeiten, die
CustomerSyncEngine
kommt mit.Wenn Sie diesem Ansatz Folgen, werden Sie wahrscheinlich benötigen einen Standard-Konstruktor ausgesetzt auf
CustomerSyncEngine
um ihm zu erlauben, zu spotten. Es ist möglich, Sie könnten das umgehen, und erfüllen die Abhängigkeiten mit null oder andere Werte, aber das wäre zusätzliche Arbeit, wenn das Ziel ist, um die Reibung zu reduzieren.InformationsquelleAutor Chris Marisic
Ich weiß, das wurde aufgefordert eine Weile her, und vielleicht nicht Wert für mich zu fügen Sie diese jetzt, aber für zukünftige Leser, lassen Sie uns nicht gefangen zu denken, dass die folgenden sind die gleiche Sache bei der Verwendung von moq:
ist nicht das gleiche wie:
Mein Verständnis ist, dass bei der Erstellung eines Mock "ifoo") vom, ist das moq-framework wird zum generieren einer Doppel-Klasse, die die "ifoo") vom interface, also die Bereitstellung der default-Konstruktor für sich selbst in der generierten Implementierung. Die mock Foo richtige, aber nicht implementiert die Schnittstelle direkt in den generierten code, sondern erbt von der konkreten Klasse " Foo " und erfordert somit keine Methoden, die Stubs werden aus virtuelle, und wenn es irgendwelche konkreten Implementierungen, die Sie wollen, um tatsächlich nutzen (unit under test, zum Beispiel), dann müssten Sie "CallBase = true" auf Ihrem Schein. Wenn dies ist, was Sie suchen, zu tun mit einer konkreten Klasse, die als argument für den Konstruktor, dem Sie suchen können für @Palkin, die Antwort zu vermeiden, dass ein default-Konstruktor.
Als edit, um die Antwort auf die Frage,
Den Rat zu extrahieren, die eine Schnittstelle kann nicht genau das sein, was du bist suchen für. Wie es bereits erwähnt wurde in anderen Antworten, wir sind nicht sicher, was es ist Sie versuchen zu testen.
Wenn Sie versuchen zu testen, Funktionalität auf die konkreten
Foo
Umsetzung vonIFoo
dann interface extrahieren und SpottIFoo
ist nicht wirklich zu helfen, weil moq wird implementieren das interface selbst und nur die "Funktionalität", sagen Sie, um in den setup-Methoden und Eigenschaften auf, die Umsetzung. Wenn dies ist, was Sie tun, UND die zu testende Methode ruft eine andere Methode auf die Beton -Foo
Umsetzung, UND, die Methode ist etwas, das Sie wollen, um eine Abstraktion, dann würde ich tun, wie @Chris Marisic erwähnt und die Methode ändern, die Sie wünschen zu abstrahieren, zuvirtual
. Mit diesem virtuellen Sie kann Verwendung eines mocking-Frameworks ein, um die Abstraktion, oder tun, was ich in der Vergangenheit getan haben, und erstellen Sie eine sub-Typ aus dem Thema unter test in der test-Klasse.Mit dieser Methode sind Sie immer noch gehen zu müssen, um etwas an den Konstruktor von Foo, aber das wäre eine prime Fall für den Einsatz von mocks, die auf diese Schnittstellen.
Nun, wenn Sie den Test
Foo
und die zu testende Methode ist nur das aufrufen von Methoden aufIBar
,IFizz
,IBuzz
, und es gibt keine andere Abstraktion, die Sie erstellen möchten, dann sind Sie schon eingerichtet. Mock jene Schnittstellen, legen Sie Sie zurück, was Sie erwarten, in einer bestimmten Testfall, und bietenFoo
mit den mock-Objekten.Dem interface extrahieren Beratung ist wirklich hilfreich, wenn Ihr Thema in der Prüfung ist abhängig von Foo, wie erwähnt von @Chris Marisic. Jedoch kann ich nicht teilen, seine Aussage für die nicht wollen, schaffen Schnittstellen in dieser situation. Es hängt davon ab, was riecht mehr für Sie: erstellen einer Schnittstelle für die Bereitstellung von mock-Fähigkeit, oder ändern Sie den Modifikator um die gleichen. Wenn du gehst, um die ändern der modifier, und noch moq zu verspotten, die konkrete
Foo
wird, müssen Sie entweder setzen Sie einen default-Konstruktor (ziemlich stinkig auf mich) oder erstellen der mock mit dem angegebenen Konstruktor Argumente Spezifikation, wie erwähnt, in Ihrer Antwort verwiesen.Können sagen, Sie haben die folgenden:
In der oben
Baz
ist abhängig vonFoo
. Nach dem extrahieren einer SchnittstelleFoo
,Baz
würde akzeptieren müssenIFoo
.Dann
Foo
Aussehen würde, wie es in Ihrer Frage undIFoo
hätte eine Signatur, die definition für die Methode, die Sie wollen, zu abstrahieren vonBaz
.Nun, in deinem test würden Sie noch verwenden
var foo = new Mock<IFoo>();
und gebenfoo
zu IhremBaz
Probanden. Vergessen Sie nicht, um den setup -IFoo.GetStuff()
Methode.Weil Sie haben nun erstellt das
IFoo
Abstraktion gibt es keine Notwendigkeit,weil die mock
IFoo
hat nur einen Standardkonstruktor zur Verfügung gestellt von moq.Ich persönlich bevorzuge den interface-Ansatz, wenn es gilt, weil es entfernt
IFizz
,IBuzz
, undIBar
aus der Abhängigkeit Kette aufBaz
. WennBaz
hängtFoo
undFoo
hängtIFizz etc.
, dannBaz
hängt auch davon abIFizz etc.
Nach dem extrahierenIFoo
,Baz
hängtIFoo
nur.InformationsquelleAutor Josh Gust
Sollten Sie nichts ändern, wenn Sie eine Schnittstelle
IFoo
und möchten mockFoo
Klasse, Konstruktor mit Parametern.Dein code ist genau das, was Sie brauchen.
Folgende Beratung erstreckt sich die Situation, wenn die Klasse hat keine Schnittstelle und keine parameterlosen Konstruktor. Eigentlich kannst du alle benötigten Parameter in Konstruktor
Mock
.aber
InformationsquelleAutor Ilya Palkin
Dies ist eine alte post, aber ich lief in ein ähnliches problem (beginnend mit Moq). Fall hat jemand ein ähnliches problem, hier ist was ich hatte:
Was ich versuche zu tun ist, prüfen Sie
Manager
nichtFoo
.Hier war mein Erster test-code, warf einen Fehler.
Den Fehler
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: Something.Models.Foo. Could not find a parameterless constructor.
Lesen der Fehlermeldung, Moq nicht verstehen, wie man zu instanziieren Foo, da es keinen parameterlosen Konstruktor hat, und wir nicht sagen, Moq, wie zum instanziieren eines mit Parameter. Ändern, dass der zweite Abschnitt:
IFoo
ist ein Tippfehler in diesen mock-Kreationen. Sollte es nichtvar fooMock = Mock<Foo>()
nach der Fehlermeldung, die Sie zur Verfügung gestellt?InformationsquelleAutor therealjumbo
Wenn Sie gehen, um Ihre tests FOo-Klasse, die Sie nicht brauchen, zu verspotten. Sie brauchen nur zu verspotten diejenigen Klassen, die abhängig von der Klasse, die Sie versuchen, zu tests.
Etwas wie:
Dann rufen Sie die Methode foo, die Sie testen möchten 😉
Wenn die Methode foo verwendet eine Methode, mit inside bar/fuzz oder fizz, dann sollten Sie die Syntax wie:
Diese Weise, wenn Sie Ihre foo-Methode aufgerufen wird, rufen die DoSomething und immer 1 zurück 😉
InformationsquelleAutor Oscar Bralo
Schnittstellen sind hilfreich, wenn Sie eine Art mehr als eine Umsetzung. Auf eine negative Seite, das heißt, Sie sollten darauf achten, nicht ableiten, Schnittstellen, nur weil Sie wollen-Schnittstellen (häufiger Fehler). Auf der positiven Seite, verspottet-Schnittstelle ist die zweite Umsetzung durch definition.
So, die Schlussfolgerung ist - wenn ein Typ wirkt als eine andere Art der Abhängigkeit, dann ist es ein guter Kandidat, um eine Schnittstelle implementieren. In diesem Fall werden Sie in der Lage zu verspotten, die Schnittstelle in unit-tests frei und vollständig.
Auf einem verwandten beachten Sie, dass bei der Definition einer Schnittstelle, stellen Sie sicher, fügen Sie nur die funktionalen Teile der Oberfläche: Methoden, die definieren, was das Objekt hat, nicht das, was es sieht aus wie. Eine Schnittstelle mit einer Menge von Getter/setter nicht den Wert auf das design. Das ist ganz große Bereich der Theorie, und diese winzige Fenster ist nicht der Ort, um mehr darüber schreiben.
Klären Zusammenhang mit Ihrer Frage: verspottet Implementierung sollte Verhalten erforderlich, die durch die Schnittstelle. Um das zu tun, verwenden Sie Funktionen der mocking framework. Das hat nichts zu tun mit der konkreten Umsetzung der Foo-Klasse definieren Sie das konkrete Verhalten des Mock-Objekts.
InformationsquelleAutor Zoran Horvat