Wenn ich Moq direkt zum Nachstellen von IBuilderFactory
und Instanziieren von BuilderService
selbst in einem Komponententest verwende, kann ich einen bestandenen Test erhalten, der sicherstellt, dass die Methode Create()
von IBuilderFactory
ist genau einmal aufgerufen.
Wenn ich jedoch Autofixtion mit AutoMoqCustomization verwende, einen Mock von IBuilderFactory
einfriere und BuilderService
mit fixture.Create<BuilderService>
instanziiere, erhalte ich die folgende Ausnahme:
System.ArgumentException: Proxy der Klasse kann nicht instanziiert werden: OddBehaviorTests.CubeBuilder. Es konnte kein Parameter gefunden werden Konstrukteur. Parametername: constructorArguments
Wenn ich CubeBuilder
versiegelt mache (dargestellt durch Ersetzen durch die versiegelte Klasse SealedCubeBuilder
, die von IBuilderFactoryForSealedBuilder.Create()
aufgerufen wird, wird der Test mit AutoFixture mit AutoMoqCustomization übergeben, ohne Ausnahme.
Vermisse ich etwas? Da ich Tests direkt mit Moq absolviere, glaube ich, dass dies mit Autofixtion und / oder AutoMoqCustomization zusammenhängt. Ist das das gewünschte Verhalten? Wenn ja, warum?
Um zu reproduzieren, verwende ich:
%Vor%Hier sind die vier Tests, die das Verhalten veranschaulichen:
%Vor%Hier sind die erforderlichen Klassen:
%Vor%Wenn Sie sich die Stack-Trace ansehen, werden Sie bemerken, dass die Ausnahme tief in Moq passiert. AutoFixture ist eine eigensinnige Bibliothek. Eine der Meinungen ist, dass Nullwerte ungültige Rückgabewerte sind . Aus diesem Grund konfiguriert AutoMoqCustomization alle Mock-Instanzen wie folgt:
%Vor%(unter anderem). Daher können Sie den fehlgeschlagenen Test vollständig ohne AutoFixture reproduzieren:
%Vor%Das Seltsame ist, dass es immer noch mit versiegelten Klassen zu arbeiten scheint. Dies ist jedoch nicht ganz richtig, sondern stammt vielmehr aus den OP-Tests, die Falsche Negative sind.
Betrachten Sie diesen Charakterisierungstest von Moq:
%Vor% Moq korrekt löst eine Ausnahme aus, weil es aufgefordert wurde, eine Instanz von CubeBuilder zu erstellen, und es weiß nicht, wie dies zu tun ist, weil CubeBuilder keinen Standardkonstruktor hat und kein Setup
sagt es, wie mit Aufrufen von Create
umzugehen.
(Nebenbei bemerkt ist die Ironie, dass AutoFixture perfekt eine Instanz von CubeBuilder erstellen könnte, aber es gibt keinen Erweiterbarkeitspunkt in Moq, der es AutoFixture ermöglicht, das Standardobjekt zur Objekterstellung von Moq zu übernehmen und zu übernehmen.)
Betrachten Sie nun diesen Charakterisierungstest, wenn ein Rückgabetyp versiegelt ist:
%Vor% Es stellt sich heraus, dass in diesem Fall, obwohl implizit gesagt wurde, dass null
nicht zurückgegeben wird, Moq dies trotzdem tut.
Meine Theorie ist, dass in MoqCharacterizationForUnsealedClass oben gesagt wird, was factory.DefaultValue = DefaultValue.Mock;
wirklich bedeutet, dass Moq einen Mock von CubeBuilder erstellt - mit anderen Worten: Es gibt dynamisch eine Klasse aus, die von CubeBuilder ableitet . Wenn Sie jedoch gebeten werden, einen Mock von SealedCubeBuilder zu erstellen, kann dies nicht geschehen, da er keine Klasse erstellen kann, die von einer versiegelten Klasse abgeleitet ist.
Anstatt eine Ausnahme auszulösen, wird null
zurückgegeben. Dies ist inkonsistentes Verhalten, und Ich habe dies als Fehler in Moq gemeldet .
Tags und Links dependency-injection moq autofixture automocking castle-dynamicproxy