ライブラリのコアには、 IFileSystemとFileSystemがあります。 File.ReadAllTextのようなメソッドを直接呼び出す代わりに、 IFileSystem.File.ReadAllTextを使用します。私たちのAPIは、注射可能でテスト可能であることを除いて、まったく同じAPIを持っています。
dotnet add package TestableIO.System.IO.Abstractions.Wrappers注:このNugetパッケージはSystem.IO.Abstractionsとしても公開されていますが、プレフィックスを使用して、これが公式の.NETパッケージではないことを明確にすることをお勧めします。
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. " ) ;
}
}
}また、図書館は、基本的なシナリオのために、すべての通話をモックアウトしなければならないことからあなたを救うために、一連のテストヘルパーが出荷されます。それらは実生活のファイルシステムの完全なコピーではありませんが、そこにほとんどの方法を手に入れることができます。
dotnet add package TestableIO.System.IO.Abstractions.TestingHelpers注:このNugetパッケージは、 System.IO.Abstractions.TestingHelpersとしても公開されていますが、プレフィックスを使用して、これが公式の.NETパッケージではないことを明確にすることをお勧めします。
[ 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. " ) ;
}.NETフレームワークのテスト不可能なタイプからテスト可能なラッパーへのキャストをサポートしています。
FileInfo SomeApiMethodThatReturnsFileInfo ( )
{
return new FileInfo ( " a " ) ;
}
void MyFancyMethod ( )
{
var testableFileInfo = ( FileInfoBase ) SomeApiMethodThatReturnsFileInfo ( ) ;
.. .
}バージョン4.0以降、トップレベルのAPIは、抽象的なベースクラスの代わりにインターフェイスを公開します(ただし、これらはまだ存在します)。ファイルシステムを完全にモックすることができます。 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 、コア抽象化の上に利便性の機能を提供します。
System.IO.Abstractions.Analyzers 、静的方法よりも抽象化を使用するのに役立つRoslynアナライザーを提供します。
Testably.Abstractions 、代替のテストヘルパーと追加の抽象化を提供します。