我有這樣處理的方法是創建一個包含只是我所需要的設備文件系統的抽象。在這個例子中,我創建了一個實用程序來從Git日誌歷史記錄中提取信息。我使所有的方法都是虛擬的,這樣他們就可以被模擬,但是你可以輕鬆定義一個接口。
/// <summary>
/// Class FileSystemService - an abstraction over file system services.
/// This class consists mainly of virtual methods and exists primarily to aid testability.
/// </summary>
public class FileSystemService
{
public virtual bool DirectoryExists(string path)
{
return Directory.Exists(path);
}
public virtual string PathCombine(string path1, string path2)
{
return Path.Combine(path1, path2);
}
public virtual string GetFullPath(string path)
{
return Path.GetFullPath(path);
}
public virtual void SaveImage(string path, Bitmap image, ImageFormat format)
{
image.Save(path, ImageFormat.Png);
}
}
在創建了文件系統服務,其注入需要它,像這樣的任何對象:
class SomeClassThatNeedsTheFileSystem
{
public SomeClassThatNeedsTheFileSystem(FileSystemService filesystem = null)
{
fileSystem = filesystem ?? new FileSystemService();
}
}
注:這是一個相當小的項目,我不想捲入與IOC容器,所以我通過使FileSystemService成爲默認值爲'null'的可選參數來做「窮人的IoC」;然後在構造函數中測試null和new FileSystemService。理想情況下,爲了獲得更健壯的代碼,我需要強制參數並強制調用者傳入FileSystemService。
當談到時間來創建一個假的,我不喜歡這樣(我使用MSpec和FakeItEasy):
// Some stuff elided for clarity
public class with_fake_filesystem_service
{
Establish context =() =>
{
Filesystem = A.Fake<FileSystemService>();
};
protected static FileSystemService Filesystem;
}