Ich habe einen Unit Test (nUnit). In vielen Schichten des Aufrufstapels schlägt eine Methode fehl, wenn sie über einen Komponententest ausgeführt wird.
Idealerweise würden Sie so etwas wie Verspotten verwenden, um das Objekt einzurichten, von dem diese Methode abhängt, aber dies ist Code von Drittanbietern, und das kann ich nicht ohne viel Arbeit tun.
Ich möchte keine nUnit-spezifischen Methoden einrichten - hier gibt es zu viele Ebenen und es ist eine schlechte Art, Unit-Tests durchzuführen.
Stattdessen möchte ich so etwas tief im Aufrufstapel hinzufügen
#IF DEBUG // Unit tests only included in debug build
if (IsRunningInUnitTest)
{
// Do some setup to avoid error
}
#endif
Also irgendwelche Ideen, wie man IsRunningInUnitTest schreibt?
PS Ich bin mir völlig bewusst, dass dies kein großartiges Design ist, aber ich denke, es ist besser als die Alternativen.
c#
reflection
nunit
Ryan
quelle
quelle
Antworten:
Ich habe das schon einmal gemacht - ich musste meine Nase halten, während ich es tat, aber ich tat es. Pragmatismus schlägt jedes Mal Dogmatismus. Natürlich, wenn es ist eine schöne Art und Weise Sie es zu vermeiden Refactoring kann, das wäre toll.
Grundsätzlich hatte ich eine "UnitTestDetector" -Klasse, die überprüfte, ob die NUnit-Framework-Assembly in die aktuelle AppDomain geladen wurde. Dies musste nur einmal durchgeführt und dann das Ergebnis zwischengespeichert werden. Hässlich, aber einfach und effektiv.
quelle
AppDomain.GetAssemblies
die relevante Assembly verwenden und nach ihr suchen - für MSTest müssten Sie sich ansehen, welche Assemblys geladen werden. Schauen Sie sich Ryans Antwort als Beispiel an.Als ich Jons Idee aufnahm, kam ich auf Folgendes:
Hinten sind wir alle groß genug, um zu erkennen, wenn wir etwas tun, was wir wahrscheinlich nicht tun sollten;)
quelle
Angepasst an Ryans Antwort. Dieser ist für das MS Unit Test Framework.
Der Grund, warum ich das brauche, ist, dass ich bei Fehlern eine MessageBox anzeige. Meine Komponententests testen jedoch auch den Fehlerbehandlungscode, und ich möchte nicht, dass beim Ausführen von Komponententests eine MessageBox angezeigt wird.
Und hier ist ein Unit-Test dafür:
quelle
Um Ryans Lösung zu vereinfachen, können Sie jeder Klasse einfach die folgende statische Eigenschaft hinzufügen:
quelle
Ich benutze einen ähnlichen Ansatz wie Tallseth
Dies ist der Basiscode, der leicht geändert werden kann, um das Caching einzuschließen. Eine weitere gute Idee wäre, einen Setter zum Haupteinstiegspunkt Ihres Projekts hinzuzufügen
IsRunningInUnitTest
und diesen aufzurufenUnitTestDetector.IsRunningInUnitTest = false
, um die Codeausführung zu vermeiden.quelle
Möglicherweise nützlich, wenn Sie den aktuellen Prozessnamen überprüfen:
Und diese Funktion sollte auch von unittest überprüft werden:
Referenzen:
Matthew Watson in http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/11e68468-c95e-4c43-b02b-7045a52b407e/
quelle
|| processName.StartsWith("testhost") // testhost.x86
für VS 2019Im Testmodus
Assembly.GetEntryAssembly()
scheint zu seinnull
.Beachten Sie, dass
Assembly.GetEntryAssembly()
istnull
,Assembly.GetExecutingAssembly()
ist es nicht.In der Dokumentation heißt es: Die
GetEntryAssembly
Methode kann zurückkehren,null
wenn eine verwaltete Assembly aus einer nicht verwalteten Anwendung geladen wurde.quelle
Irgendwo im getesteten Projekt:
Irgendwo in Ihrem Unit-Test-Projekt:
Elegant, nein. Aber unkompliziert und schnell.
AssemblyInitializer
ist für MS Test. Ich würde erwarten, dass andere Test-Frameworks Äquivalente haben.quelle
IsRunningInUnitTest
wird dieser in diesen AppDomains nicht auf true gesetzt.Ich benutze das nur zum Überspringen von Logik, die alle TraceAppender in log4net während des Startvorgangs deaktiviert, wenn kein Debugger angeschlossen ist. Auf diese Weise können Komponententests auch im Nicht-Debug-Modus im Resharper-Ergebnisfenster protokolliert werden.
Die Methode, die diese Funktion verwendet, wird entweder beim Start der Anwendung oder beim Starten eines Testgeräts aufgerufen.
Es ähnelt Ryans Post, verwendet jedoch LINQ, löscht die System.Reflection-Anforderung, speichert das Ergebnis nicht im Cache und ist privat, um (versehentlichen) Missbrauch zu verhindern.
quelle
Ein Verweis auf das Nunit-Framework bedeutet nicht, dass der Test tatsächlich ausgeführt wird. Wenn Sie beispielsweise in Unity Tests für den Wiedergabemodus aktivieren, werden dem Projekt die Nunit-Referenzen hinzugefügt. Und wenn Sie ein Spiel ausführen, sind die Referenzen vorhanden, sodass UnitTestDetector nicht richtig funktioniert.
Anstatt nach der Versammlung von nunit zu suchen, können wir nuni api bitten, zu überprüfen, ob der Code gerade ausgeführt wird oder nicht.
Bearbeiten:
Beachten Sie, dass der TestContext bei Bedarf automatisch generiert wird.
quelle
Verwenden Sie einfach dies:
Im Testmodus wird false zurückgegeben.
quelle
Ich war unglücklich, dieses Problem kürzlich zu haben. Ich habe es etwas anders gelöst. Erstens wollte ich nicht davon ausgehen, dass das Nunit-Framework niemals außerhalb einer Testumgebung geladen wird. Ich war besonders besorgt über Entwickler, die die App auf ihren Computern ausführen. Also ging ich stattdessen den Anrufstapel entlang. Zweitens konnte ich davon ausgehen, dass Testcode niemals für Release-Binärdateien ausgeführt werden würde, und stellte daher sicher, dass dieser Code in einem Release-System nicht vorhanden ist.
quelle
klappt wunderbar
.
quelle
Unit-Tests überspringen den Einstiegspunkt der Anwendung. Zumindest für wpf werden Winforms und Konsolenanwendungen
main()
nicht aufgerufen.Wenn die Hauptmethode aufgerufen wird, befinden wir uns zur Laufzeit , andernfalls befinden wir uns im Unit-Test- Modus:
quelle
Wenn Sie bedenken, dass Ihr Code normalerweise im Hauptthread (GUI) einer Windows Forms-Anwendung ausgeführt wird und Sie möchten, dass er sich während der Ausführung eines Tests, auf den Sie prüfen können, anders verhält
Ich verwende dies für Code, den ich
fire and forgot
in einer GUI-Anwendung verwenden möchte, aber in den Komponententests benötige ich möglicherweise das berechnete Ergebnis für eine Bestätigung und möchte nicht mit mehreren laufenden Threads herumspielen.Funktioniert für MSTest. Der Vorteil ist, dass mein Code nicht nach dem Testframework selbst suchen muss und wenn ich das asynchrone Verhalten in einem bestimmten Test wirklich benötige, kann ich meinen eigenen SynchronizationContext festlegen.
Beachten Sie, dass dies keine zuverlässige Methode ist,
Determine if code is running as part of a unit test
wie von OP angefordert, da Code möglicherweise in einem Thread ausgeführt wird. In bestimmten Szenarien kann dies jedoch eine gute Lösung sein (auch: Wenn ich bereits von einem Hintergrund-Thread ausgeführt werde, ist dies möglicherweise nicht erforderlich einen neuen starten).quelle
Application.Current ist null, wenn es unter dem Unit-Tester ausgeführt wird. Zumindest für meine WPF-App mit MS Unit Tester. Dies ist bei Bedarf ein einfacher Test. Beachten Sie auch Folgendes, wenn Sie Application.Current in Ihrem Code verwenden.
quelle
Ich habe Folgendes in VB in meinem Code verwendet, um zu überprüfen, ob wir in einem Komponententest sind. Insbesondere wollte ich nicht, dass der Test Word öffnet
quelle
Wie wäre es mit Reflexion und so etwas:
var underTest = Assembly.GetCallingAssembly ()! = typeof (MainForm) .Assembly;
In der aufrufenden Assembly befinden sich Ihre Testfälle und ersetzen nur MainForm durch einen Typ, der in Ihrem zu testenden Code enthalten ist.
quelle
Es gibt auch eine wirklich einfache Lösung, wenn Sie eine Klasse testen ...
Geben Sie einfach der Klasse, in der Sie eine Eigenschaft testen, Folgendes an:
Jetzt kann Ihr Komponententest den Booleschen Wert "thisIsUnitTest" auf "true" setzen. Fügen Sie also in dem Code, den Sie überspringen möchten, Folgendes hinzu:
Es ist einfacher und schneller als die Inspektion der Baugruppen. Erinnert mich an Ruby On Rails, wo Sie nachsehen würden, ob Sie sich in der TEST-Umgebung befinden.
quelle