Warum hört Autoftixture mit AutoMoqCustomization auf, sich über das Fehlen eines parameterlosen Konstruktors zu beschweren, wenn die Klasse versiegelt ist?

8

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%     
Jeff 09.08.2013, 20:21
quelle

1 Antwort

11

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 .

    
Mark Seemann 11.08.2013, 08:19
quelle