Im Kern der Bibliothek befindet sich IFileSystem
und FileSystem
. Verwenden IFileSystem.File.ReadAllText
anstatt Methoden wie File.ReadAllText
direkt aufzurufen. Wir haben genau die gleiche API, außer dass unsere injizierbare und überprüfbare API ist.
dotnet add package TestableIO.System.IO.Abstractions.Wrappers
HINWEIS: Dieses Nuget -Paket wird auch als System.IO.Abstractions
veröffentlicht. Wir empfehlen jedoch, das Präfix zu verwenden, um klarzustellen, dass dies kein offizielles .NET -Paket ist.
public class MyComponent
{
readonly IFileSystem fileSystem ;
// <summary>Create MyComponent with the given fileSystem implementation</summary>
public MyComponent ( IFileSystem fileSystem )
{
this . fileSystem = fileSystem ;
}
/// <summary>Create MyComponent</summary>
public MyComponent ( ) : this (
fileSystem : new FileSystem ( ) //use default implementation which calls System.IO
)
{
}
public void Validate ( )
{
foreach ( var textFile in fileSystem . Directory . GetFiles ( @"c:" , " *.txt " , SearchOption . TopDirectoryOnly ) )
{
var text = fileSystem . File . ReadAllText ( textFile ) ;
if ( text != " Testing is awesome. " )
throw new NotSupportedException ( " We can't go on together. It's not me, it's you. " ) ;
}
}
}
Die Bibliothek wird auch mit einer Reihe von Testhelfern versendet, um Sie vor dem Verspotteten jeden Anrufs für grundlegende Szenarien zu bewahren. Sie sind keine vollständige Kopie eines realen Dateisystems, aber sie werden den größten Teil des Weges dorthin bringen.
dotnet add package TestableIO.System.IO.Abstractions.TestingHelpers
Hinweis: Dieses Nuget -Paket wird auch als System.IO.Abstractions.TestingHelpers
veröffentlicht. Wir empfehlen jedoch, das Präfix zu verwenden, um klarzustellen, dass dies kein offizielles .NET -Paket ist.
[ Test ]
public void MyComponent_Validate_ShouldThrowNotSupportedExceptionIfTestingIsNotAwesome ( )
{
// Arrange
var fileSystem = new MockFileSystem ( new Dictionary < string , MockFileData >
{
{ @"c:myfile.txt" , new MockFileData ( " Testing is meh. " ) } ,
{ @"c:demojQuery.js" , new MockFileData ( " some js " ) } ,
{ @"c:demoimage.gif" , new MockFileData ( new byte [ ] { 0x12 , 0x34 , 0x56 , 0xd2 } ) }
} ) ;
var component = new MyComponent ( fileSystem ) ;
try
{
// Act
component . Validate ( ) ;
}
catch ( NotSupportedException ex )
{
// Assert
Assert . That ( ex . Message , Is . EqualTo ( " We can't go on together. It's not me, it's you. " ) ) ;
return ;
}
Assert . Fail ( " The expected exception was not thrown. " ) ;
}
Wir unterstützen sogar das Casting von den nicht testbaren Typen des .NET Framework bis zu unseren Testable Wrappers:
FileInfo SomeApiMethodThatReturnsFileInfo ( )
{
return new FileInfo ( " a " ) ;
}
void MyFancyMethod ( )
{
var testableFileInfo = ( FileInfoBase ) SomeApiMethodThatReturnsFileInfo ( ) ;
.. .
}
Da Version 4.0 die obersten APIs anstelle von abstrakten Basisklassen (diese sind jedoch noch vorhanden) Grenzflächen freigesetzt werden, können Sie das Dateisystem vollständig verspottet. Hier ist ein kleines Beispiel mit MOQ:
[ Test ]
public void Test1 ( )
{
var watcher = Mock . Of < IFileSystemWatcher > ( ) ;
var file = Mock . Of < IFile > ( ) ;
Mock . Get ( file ) . Setup ( f => f . Exists ( It . IsAny < string > ( ) ) ) . Returns ( true ) ;
Mock . Get ( file ) . Setup ( f => f . ReadAllText ( It . IsAny < string > ( ) ) ) . Throws < OutOfMemoryException > ( ) ;
var unitUnderTest = new SomeClassUsingFileSystemWatcher ( watcher , file ) ;
Assert . Throws < OutOfMemoryException > ( ( ) => {
Mock . Get ( watcher ) . Raise ( w => w . Created += null , new System . IO . FileSystemEventArgs ( System . IO . WatcherChangeTypes . Created , @"C:SomeDirectory" , " Some.File " ) ) ;
} ) ;
Mock . Get ( file ) . Verify ( f => f . Exists ( It . IsAny < string > ( ) ) , Times . Once ) ;
Assert . True ( unitUnderTest . FileWasCreated ) ;
}
public class SomeClassUsingFileSystemWatcher
{
private readonly IFileSystemWatcher _watcher ;
private readonly IFile _file ;
public bool FileWasCreated { get ; private set ; }
public SomeClassUsingFileSystemWatcher ( IFileSystemWatcher watcher , IFile file )
{
this . _file = file ;
this . _watcher = watcher ;
this . _watcher . Created += Watcher_Created ;
}
private void Watcher_Created ( object sender , System . IO . FileSystemEventArgs e )
{
FileWasCreated = true ;
if ( _file . Exists ( e . FullPath ) )
{
var text = _file . ReadAllText ( e . FullPath ) ;
}
}
}
System.IO.Abstractions.Extensions
bietet Convenience -Funktionen neben den Kernabstraktionen.
System.IO.Abstractions.Analyzers
stellt Roslyn -Analysatoren zur Verfügung, um Abstraktionen über statische Methoden zu verwenden.
Testably.Abstractions
bietet alternative Testhelfer und zusätzliche Abstraktionen.