Wir haben viele Tests mit 'Class.ReceivedCalls()' und 'var tmp = Class.Received(int).Property;' um die Anrufanzahl zu überprüfen. In v3 von AutoFixture hat es die Anrufanzahl korrekt gemeldet, insbesondere von Eigenschaften, was es nicht mehr tut. Die Aufrufanzahl der Methoden scheint noch in Ordnung zu sein.
Vorausgesetzt, wir haben den folgenden Code:
public interface IRunSpeed
{
int Speed { get; }
}
public class GetToDaChoppa
{
private readonly IRunSpeed _runSpeed;
public GetToDaChoppa(IRunSpeed runSpeed)
{
_runSpeed = runSpeed ?? throw new ArgumentNullException(nameof(runSpeed));
}
public void DoItNow()
{
var runningSpeed = _runSpeed.Speed;
}
}
Und da wir die folgenden Tests haben:
[Fact]
public void DoItNow_WithOutAutoNSubstitute()
{
// Arrange
var runSpeed = Substitute.For<IRunSpeed>();
runSpeed.Speed.Returns(2);
var sut = new GetToDaChoppa(runSpeed);
//Act
sut.DoItNow();
//Assert
var tmp = runSpeed.Received(1).Speed;
Assert.Single(runSpeed.ReceivedCalls());
}
[Theory, AutoNSubstituteData]
public void DoItNow_UsingAutoNSubstitute(
[Frozen] IRunSpeed runSpeed,
GetToDaChoppa sut)
{
// Arrange
runSpeed.Speed.Returns(49);
//Act
sut.DoItNow();
//Assert
var tmp = runSpeed.Received(1).Speed;
Assert.Single(runSpeed.ReceivedCalls());
Mein AutoNSubstituteDataAttribute sieht so aus:
public class AutoNSubstituteDataAttribute : AutoDataAttribute
{
public AutoNSubstituteDataAttribute()
: base(() => new Fixture()
.Customize(new AutoNSubstituteCustomization()))
{
}
}
Der erste Test 'DoItNow_WithOutAutoNSubstitute' funktioniert einwandfrei. Aber der zweite Test 'DoItNow_UsingAutoNSubstitute' gibt 2 für 'ios.Received(1).Speed;' zurück.
Es gibt auch 2 für 'runSpeed.ReceivedCalls();' zurück.
Aus diesem Grund können wir unsere Lösungen derzeit nicht auf v4 aktualisieren, da wir sofort >1000 fehlgeschlagene Tests pro Lösung haben. Gibt es eine Anleitung, was das Problem sein könnte oder wo man nach der Lösung suchen kann?
Danke, dass du das Problem ausgelöst hast. Eigentlich hat dieses Problem nichts mit AutoFixture zu tun, obwohl wir auch davon betroffen sind 😕
Dieses Problem wird hauptsächlich durch xUnit verursacht und wenn Sie den Test wie folgt neu schreiben, wird er bestanden:
```c#
[Theorie, AutoNSubstituteData]
public void DoItNow_UsingAutoNSubstitute_CreateManually(IFixture Fixture)
{
// Arrangieren
var runSpeed = Fixture.Freeze
var sut = Fixture.Create
runSpeed.Speed.Returns(49);
//Act
sut.DoItNow();
//Assert
var tmp = runSpeed.Received(1).Speed;
Assert.Single(runSpeed.ReceivedCalls());
}
```
Wenn Sie Tests ausführen, versucht xUnit, den Testnamen für Sie zu formatieren. Wenn es feststellt, dass der Typ nicht bekannt ist und keine ToString()
Überladung vorliegt, verwendet es die strukturelle Inspektion und ruft die Eigenschaftswerte rekursiv ab. Wenn Sie den Testnamen überprüfen, sehen Sie Folgendes:
Wie Sie vielleicht bemerken, hat xUnit den Eigenschaftswert Speed
abgerufen, um Ihnen das Testargument gut zu zeigen. Da dies ein üblicher Aufruf ist, hat NSubstitute dies als Aufruf gezählt.
Es ist ziemlich seltsam, dass Sie dieses Problem mit v3 nicht hatten, da sich diesbezüglich nichts geändert hat. Ich habe gerade xUnit2 + AutoFixture v3
getestet und habe immer noch das Problem. Wahrscheinlich haben Sie auch die xUnit aktualisiert.
Als Workaround habe ich gute und schlechte Nachrichten. Die gute Nachricht ist, dass dies in der nächsten Hauptversion von NSubsitute behoben wird, da die Methode ToString()
überschrieben wurde, um eine Proxy-ID zurückzugeben. Als Ergebnis berührt xUnit die Eigenschaften nicht mehr:
Die schlechte Nachricht ist, dass NSubsitute v4 noch nicht veröffentlicht wurde.
Ich könnte dir entweder vorschlagen:
master
Quellcode von NSubsitute, erstellen Sie einen lokalen Build und verwenden Sie Ihr eigenes NSubsitute.dll
anstelle des NuGet-Pakets. Nach der Veröffentlichung von v4 können Sie zum NuGet-Paket wechseln.Ich entschuldige mich für die Unannehmlichkeiten, aber leider können wir auf der AutoFixture-Seite nichts tun, um dieses Problem zu beheben.
habe das gerade getestet. Schließlich haben unsere Tests, die ReceivedCalls bestätigen, wieder ein erfolgreiches Ergebnis erzielt.
Etwas, das immer noch fehlschlägt, sind die Asserts auf Received(x) wie Received(1).Speed Daniel, die oben erwähnt wurden.
Habt ihr auch eine Antwort/Lösung für Hut?
Arbeitet ihr am selben Projekt? :) Wenn ja, könnten Sie klarstellen, wie Sie das Problem behoben haben?
Die oben vorgeschlagenen Optionen sollten bei beiden Problemen helfen. Wenn sie dies nicht tun, klären Sie das Szenario.
nicht wirklich das gleiche Projekt, sondern bei der gleichen Firma.
wir sind schon lange auf xunit 1.9 + nsubstitute 2 / 3 und haben es endlich geschafft, unsere internen Assemblies (Nuget-Pakete) zu bekommen, also ist ein einfacher Weg zurück zu einer älteren Version von nur einer Referenz nicht so einfach, wie es sich anhört sein) kompatibel zu xunit2 sein. und jetzt haben wir diese beiden probleme.
Wir haben schon einiges ausprobiert und dachten schließlich, dass es etwas mit Autofixture zu tun haben muss - wegen des Frozen-Attributs und einer hartcodierten Testausführungszählung - oder so ähnlich.
nachdem daniel diesen fall eröffnet hat, hat er mir den link dazu gepostet.
genau wie Sie oben beschrieben haben, habe ich die Nuget 3.1-Referenz durch die aus dem frisch kompilierten nsubstitute-Projekt ersetzt. danach habe ich jetzt 118 statt 178 fehlgeschlagene Tests, weil Receiced(x) immer noch die falsche Anzahl von Anrufen auswertet.
mein Projekt basiert derzeit auf .net 4.5.2 mit xunit2, aktueller Repo-Version von nsubstitute und referenziert auf Autofixture 4.2. alle Tests schlagen aus den gleichen zwei Gründen fehl - außerdem gibt es immer noch einige empfangene Anrufe, die in den Komponententests fehlschlagen.
Ich glaube, ich muss mir das nochmal genauer anschauen, wenn ich wieder im Büro bin (Ostern unterwegs).
vielleicht kann @dklinger mittlerweile das Szenario beschreiben.
@dklinger @evilbaschdi Bitte installiert haben.
Öffnen Sie das Problem erneut, um anzugeben, dass die Ermittlungen noch andauern.
Ok, also ich habe die letzten Stunden getestet. Erstens: Danke für deine Antwort, deine Erklärung und die Vorschläge - das hat sehr geholfen.
Ich habe v4 von NSubstitute getestet. Es funktioniert für meinen obigen Beispielcode, löst das Problem jedoch nicht vollständig in unseren realen Projekten. Das Problem ist, dass es das Problem der falschen ReceivedCalls-Zählung nur für SUT-Aufrufe an Methoden, nicht an Eigenschaften, behebt.
Beispiel für unseren jetzt funktionierenden Code:
[Theory, AutoNSubstituteData]
public void DoItNow_UsingAutoNSubstitute(
[Frozen] IRunSpeed runSpeed,
GetToDaChoppa sut)
{
// Arrange
runSpeed.Speed.Returns(49);
//Act
sut.DoItNow();
//Assert
var tmp = runSpeed.Received(1).Speed;
Assert.Equal(1, runSpeed.ReceivedCalls().Count());
}
Aber wenn ich die Methode "GetToDaChoppa.DoItNow();" ändere um eine Eigenschaft "GetToDaChoppa.DoItNow" zu sein, ist ReceivedCallsCount wieder +1:
[Theory, AutoNSubstituteData]
public void DoItNow_UsingAutoNSubstitute(
[Frozen] IRunSpeed runSpeed,
GetToDaChoppa sut)
{
// Arrange
runSpeed.Speed.Returns(49);
//Act
var x = sut.DoItNow;
//Assert
var tmp = runSpeed.Received(1).Speed;
Assert.Equal(1, runSpeed.ReceivedCalls().Count());
}
Ich denke, es hat wieder mit der xUnit-Namensgebung zu tun, da wir diese für die Arbeitsmethode-Implementierung bekommen:
Und das für die nicht funktionierende Property-Implementierung:
Es sieht so aus, als ob xUnit die SUT-Eigenschaft aufruft, um ihren Wert abzurufen, um ihn für den Testnamen zu verwenden, aber dies tut es nicht für SUT-Methoden. Mein erster Gedanke war, dass es mit dem Rückgabewert unserer Methode "GetToDaChoppa()" zu tun hat, die void war. Aber selbst nachdem es in "public int GetToDaChoppa()" geändert wurde, ruft xUnit es immer noch nicht auf, um einen Rückgabewert für den Testnamen zu erhalten. Es ist nur ein Problem mit Eigenschaften.
Im Moment stecke ich wieder fest. Ich stimme voll und ganz zu, dass dies kein Problem von AutoFixture ist. Aber wenn Sie alle Pakete besser kennen als wir, was würden Sie Ihrer Meinung nach vorschlagen?
@dklinger Danke fürs Nachfassen! Könnten Sie bitte den MCVE- Code für das letzte Szenario, das immer noch fehlschlägt, teilen? Nur damit nichts übersehen wird und ich die Bedingungen nicht falsch verstanden habe.
Danach werde ich versuchen zu untersuchen, warum das passiert und wie man das umgehen kann.
Vielen Dank.
Ja, sicher. Hier ist es:
System im Test:
public interface IRunSpeed
{
int Speed { get; }
void Dude();
int Dude2();
}
public class GetToDaChoppa
{
private readonly IRunSpeed _runSpeed;
public GetToDaChoppa(IRunSpeed runSpeed)
{
_runSpeed = runSpeed ?? throw new ArgumentNullException(nameof(runSpeed));
}
public int DoItNow
{
get
{
var runningSpeed = _runSpeed.Speed;
return 0;
}
}
}
Testfall:
[Theory, AutoNSubstituteData]
public void DoItNowAsProperty_UsingAutoNSubstitute(
[Frozen] IRunSpeed runSpeed,
GetToDaChoppa sut)
{
// Arrange
runSpeed.Speed.Returns(49);
//Act
var x = sut.DoItNow;
//Assert
var tmp = runSpeed.Received(1).Speed;
Assert.Equal(1, runSpeed.ReceivedCalls().Count());
}
Aktuell versuche ich die Diskussionen unter https://github.com/xunit/xunit/issues/1386 und https://github.com/AutoFixture/AutoFixture/issues/805 nachzuholen. Vielleicht machen wir etwas falsch oder es gibt eine Möglichkeit, xUnit anzuweisen, den Testnamen nicht automatisch zu generieren.
Ich habe auch versucht, mein eigenes TheoryAttribute zu erstellen, das die DisplayName-Eigenschaft überschreibt, aber das hilft auch nicht, da xUnit in gewisser Weise immer noch den automatisch generierten Namen intern verwendet. Aber das ist nur zu Ihrer Information und hat nichts mit dem obigen Demo-Code zu tun.
public sealed class MyTheoryAttribute : TheoryAttribute
{
public MyTheoryAttribute([CallerMemberName] string memberName = null)
{
DisplayName = "MyTestCase";
}
}
Hallo, ich nochmal :)
Es ist tatsächlich xUnit2, das alle Eigenschaften und Felder von Testmethodenparametern aufruft, die von einem komplexen Typ sind. Die Codezeile ist diese: https://github.com/xunit/assert.xunit/blob/2b70a9b0c5bb291f98472ec24cec437acf8d65c8/Sdk/ArgumentFormatter.cs#L156
Danke für deine Unterstützung. Ich habe ein Problem im xUnit-Repo wieder geöffnet, wo die Diskussion weitergehen sollte: https://github.com/xunit/xunit/issues/1682
@dklinger Danke für das ausführliche Szenario. Es ist in der Tat ziemlich knifflig und es ist schwer, es irgendwie zu umgehen. Aus AutoFixture- und NSubsitute-Sicht gibt es keinen Unterschied, ob Code irgendwo tief in xUnit oder im Testkörper aufgerufen wird.
Normalerweise können Sie als Workaround die klare Funktion von NSubstitute verwenden:
runSpeed.ClearReceivedCalls();
Dieser Code sollte beim Prolog jedes Tests ausgeführt werden, bei dem Sie die genaue Anzahl der Anrufe überprüfen. Es funktioniert gut, wenn Sie ein paar Tests haben, aber wenn Tausende von Tests betroffen sind, wird es natürlich nicht viel helfen 😅
Es ist schade, dass die Integration von NSubsitute + xUnit2 + AutoFixture nicht gut funktioniert und unter solchen Problemen leidet. AutoFixture-Produkt wurde entwickelt, um das Leben zu vereinfachen, anstatt es zu einem Albtraum zu machen 😕 Ich hoffe, die Jungs von xUnit werden Ihnen einen schnellen Weg zur Lösung des Problems für das gesamte Projekt geben.
Lassen Sie es mich wissen, wenn Sie glauben, dass wir von unserer Seite aus etwas tun können, um die Situation zu verbessern.