Gibt es Bibliotheken oder Methoden, um das Dateisystem in C # zu verspotten und Unit-Tests zu schreiben? In meinem aktuellen Fall habe ich Methoden, die prüfen, ob eine bestimmte Datei vorhanden ist, und das Erstellungsdatum lesen. Vielleicht brauche ich in Zukunft mehr.
c#
unit-testing
mocking
pupeno
quelle
quelle
Antworten:
Bearbeiten: Installieren Sie das NuGet-Paket
System.IO.Abstractions
.Dieses Paket existierte nicht, als diese Antwort ursprünglich akzeptiert wurde. Die ursprüngliche Antwort wird für den historischen Kontext unten bereitgestellt:
quelle
Diese imaginäre Bibliothek existiert jetzt, es gibt ein NuGet-Paket für System.IO.Abstractions , das den System.IO-Namespace abstrahiert.
Es gibt auch eine Reihe von Testhelfern, System.IO.Abstractions.TestingHelpers, die zum Zeitpunkt des Schreibens nur teilweise implementiert sind, aber einen sehr guten Ausgangspunkt darstellen.
quelle
Sie müssen wahrscheinlich einen Vertrag erstellen, um zu definieren, welche Dinge Sie vom Dateisystem benötigen, und dann einen Wrapper um diese Funktionen schreiben. An diesem Punkt können Sie die Implementierung verspotten oder stummschalten.
Beispiel:
quelle
Ich empfehle, http://systemwrapper.codeplex.com/ zu verwenden, da es Wrapper für die am häufigsten verwendeten Typen im System-Namespace bereitstellt
quelle
Ich bin auf folgende Lösungen gestoßen:
Am Ende verwende ich alle oben genannten Methoden, je nachdem, was ich schreibe. Aber die meiste Zeit denke ich, dass Abstraktion falsch ist, wenn ich Unit-Tests schreibe, die die E / A treffen.
quelle
Mit System.IO.Abstractions und System.IO.Abstractions.TestingHelpers wie folgt :
In Ihrer Testklasse verwenden Sie MockFileSystem (), um Dateien zu verspotten, und Sie instanziieren ManageFile wie folgt:
quelle
Sie können dies mit Microsoft Fakes tun, ohne Ihre Codebasis ändern zu müssen, z. B. weil sie bereits eingefroren war.
Zuerst ein gefälschte erzeugen Baugruppe für System.dll - oder ein anderes Paket und dann erwartete Renditen verspotten , wie in:
quelle
Es wäre schwierig, das Dateisystem in einem Test zu verspotten, da die .NET-Datei-APIs nicht wirklich auf Schnittstellen oder erweiterbaren Klassen basieren, die verspottet werden könnten.
Wenn Sie jedoch über eine eigene Funktionsschicht für den Zugriff auf das Dateisystem verfügen, können Sie dies in einem Komponententest verspotten.
Als Alternative zum Verspotten sollten Sie nur die Ordner und Dateien erstellen, die Sie im Rahmen Ihres Test-Setups benötigen, und diese in Ihrer Teardown-Methode löschen.
quelle
Ich bin mir nicht sicher, wie Sie das Dateisystem verspotten würden. Was Sie tun können, ist ein Test-Fixture-Setup zu schreiben, das einen Ordner usw. mit der erforderlichen Struktur für die Tests erstellt. Eine Teardown-Methode würde es nach dem Testlauf bereinigen.
Bearbeitet, um hinzuzufügen: Wenn Sie etwas mehr darüber nachdenken, möchten Sie das Dateisystem nicht verspotten, um diese Art von Methoden zu testen. Wenn Sie das Dateisystem verspotten, um true zurückzugeben, wenn eine bestimmte Datei vorhanden ist, und dies in Ihrem Test einer Methode verwenden, die prüft, ob diese Datei vorhanden ist, testen Sie nicht viel von irgendetwas. Das Verspotten des Dateisystems ist nützlich, wenn Sie eine Methode testen möchten, die vom Dateisystem abhängig ist, deren Dateisystemaktivität jedoch nicht in die zu testende Methode integriert ist.
quelle
Um Ihre spezielle Frage zu beantworten: Nein, es gibt keine Bibliotheken, mit denen Sie Datei-E / A-Aufrufe verspotten können (von denen ich weiß). Dies bedeutet, dass Sie für "ordnungsgemäße" Unit-Tests Ihrer Typen diese Einschränkung berücksichtigen müssen, wenn Sie Ihre Typen definieren.
Kurze Randnotiz darüber, wie ich einen "richtigen" Komponententest definiere. Ich glaube, dass Unit-Tests bestätigen sollten, dass Sie die erwartete Ausgabe erhalten (sei es eine Ausnahme, ein Aufruf einer Methode usw.), sofern bekannte Eingaben vorliegen. Auf diese Weise können Sie Ihre Unit-Test-Bedingungen als eine Reihe von Eingängen und / oder Eingangszuständen einrichten. Der beste Weg, dies zu tun, besteht darin, schnittstellenbasierte Dienste und Abhängigkeitsinjektion zu verwenden, sodass jede Verantwortung außerhalb eines Typs über eine Schnittstelle bereitgestellt wird, die über einen Konstruktor oder eine Eigenschaft übergeben wird.
In diesem Sinne zurück zu Ihrer Frage. Ich habe Dateisystemaufrufe verspottet, indem ich eine
IFileSystemService
Schnittstelle zusammen mit einerFileSystemService
Implementierung erstellt habe, die lediglich eine Fassade über die Dateisystemmethoden von mscorlib darstellt. Mein Code verwendet dannIFileSystemService
eher den Typ als den mscorlib-Typ. Auf diese Weise kann ich meinen Standard anschließen,FileSystemService
wenn die Anwendung ausgeführt wird, oder dieIFileSystemService
in meinen Komponententests verspotten . Der Anwendungscode ist unabhängig von der Ausführung identisch, aber die zugrunde liegende Infrastruktur ermöglicht das einfache Testen dieses Codes.Ich werde anerkennen, dass es schwierig ist, den Wrapper um die mscorlib-Dateisystemobjekte zu verwenden, aber in diesen speziellen Szenarien lohnt sich die zusätzliche Arbeit, da das Testen so viel einfacher und zuverlässiger wird.
quelle
Das Erstellen und Verspotten einer Schnittstelle zum Testen ist der sauberste Weg. Als Alternative können Sie sich jedoch das Microsoft Moles- Framework ansehen .
quelle
Die übliche Lösung ist die Verwendung einer abstrakten Dateisystem-API (wie Apache Commons VFS für Java): Die gesamte Anwendungslogik verwendet eine API, und der Komponententest kann ein reales Dateisystem mit einer Stub-Implementierung (In-Memory-Emulation oder ähnliches) verspotten.
Für C # existiert die ähnliche API: NI.Vfs, die Apache VFS V1 sehr ähnlich ist. Es enthält Standardimplementierungen sowohl für das lokale Dateisystem als auch für das In-Memory-Dateisystem (die letzte kann in Komponententests aus der Box verwendet werden).
quelle
Wir verwenden derzeit eine proprietäre Daten-Engine und ihre API wird nicht als Schnittstellen verfügbar gemacht, sodass wir unseren Datenzugriffscode kaum einem Unit-Test unterziehen können. Dann ging ich auch mit Matt und Joseph vor.
quelle
Ich würde der Antwort von Jamie Ide folgen. Versuchen Sie nicht, Dinge zu verspotten, die Sie nicht geschrieben haben. Es wird alle Arten von Abhängigkeiten geben, von denen Sie nichts wussten - versiegelte Klassen, nicht virtuelle Methoden usw.
Ein anderer Ansatz wäre, die entsprechenden Methoden mit etwas zu verpacken, das verspottbar ist. Erstellen Sie beispielsweise eine Klasse namens FileWrapper, die den Zugriff auf die File-Methoden ermöglicht, die Sie jedoch verspotten können.
quelle