في صميم المكتبة هو IFileSystem
و FileSystem
. بدلاً من استدعاء طرق مثل File.ReadAllText
مباشرة ، استخدم IFileSystem.File.ReadAllText
. لدينا بالضبط نفس واجهة برمجة التطبيقات ، باستثناء أن لدينا حقن وقابلة للاختبار.
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 Framework غير القابلة للتشغيل إلى الأغلفة القابلة للاختبار لدينا:
FileInfo SomeApiMethodThatReturnsFileInfo ( )
{
return new FileInfo ( " a " ) ;
}
void MyFancyMethod ( )
{
var testableFileInfo = ( FileInfoBase ) SomeApiMethodThatReturnsFileInfo ( ) ;
.. .
}
نظرًا لأن الإصدار 4.0 يعرض واجهات برمجة التطبيقات ذات المستوى الأعلى واجهات بدلاً من فئات الأساس المجردة (لا تزال موجودة ، على الرغم من ذلك) ، مما يتيح لك السخرية من نظام الملفات تمامًا. إليك مثال صغير ، باستخدام 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
absstractions.