ユニットテストを作成するためにC#でファイルシステムをモックアウトするライブラリまたはメソッドはありますか?私の現在のケースでは、特定のファイルが存在するかどうかを確認し、作成日を読み取るメソッドがあります。将来的にはそれ以上のものが必要になるかもしれません。
ユニットテストを作成するためにC#でファイルシステムをモックアウトするライブラリまたはメソッドはありますか?私の現在のケースでは、特定のファイルが存在するかどうかを確認し、作成日を読み取るメソッドがあります。将来的にはそれ以上のものが必要になるかもしれません。
回答:
編集:NuGetパッケージをインストールしますSystem.IO.Abstractions
。
この回答が最初に受け入れられたとき、このパッケージは存在しませんでした。元の回答は、以下の歴史的背景に提供されています。
あなたはインターフェースを作成することでそれを行うことができます:
interface IFileSystem { bool FileExists(string fileName); DateTime GetCreationDate(string fileName); }
そして、System.IO.File.Exists()などを使用する「実際の」実装を作成します。次に、モックフレームワークを使用してこのインターフェイスをモックできます。Moqをお勧めします。
編集:誰かがこれを行い、親切にここにオンラインで投稿しました。
私はこのアプローチを使用して、IClockインターフェイス(時間の流れを制御できるようにするためのテストに本当に役立ちます)でDateTime.UtcNowをモックアウトしました。より伝統的には、ISqlDataAccessインターフェイスです。
別のアプローチはTypeMockを使用することかもしれません。これにより、クラスへの呼び出しをインターセプトしてそれらをスタブ化することができます。ただし、これにはコストがかかり、実行するためにチーム全体のPCとビルドサーバーにインストールする必要があります。また、mscorlibをスタブできないため、System.IO.Fileでは機能しないようです。
また、特定のメソッドが単体テストできないことを受け入れ、別の実行速度の遅い統合/システムテストスイートでそれらをテストすることもできます。
この架空のライブラリは現在存在しています。System.IO名前空間を抽象化するSystem.IO.Abstractionsの NuGetパッケージがあります。
テストヘルパーのセット、System.IO.Abstractions.TestingHelpersもあります。これは、執筆時点では部分的にのみ実装されていますが、非常に優れた出発点です。
おそらく、ファイルシステムから必要なものを定義するコントラクトを作成し、それらの機能のラッパーを作成する必要があります。その時点で、実装をモックまたはスタブできるようになります。
例:
interface IFileWrapper { bool Exists(String filePath); }
class FileWrapper: IFileWrapper
{
bool Exists(String filePath) { return File.Exists(filePath); }
}
class FileWrapperStub: IFileWrapper
{
bool Exists(String filePath)
{ return (filePath == @"C:\myfilerocks.txt"); }
}
私の推奨は、http://systemwrapper.codeplex.com/を使用する ことです。これは、システム名前空間で主に使用される型のラッパーを提供するためです。
私はこれに対する以下の解決策を見つけました:
書いている内容に応じて、上記のすべての方法を使用します。しかし、ほとんどの場合、IOにヒットする単体テストを作成すると、抽象化が間違っていると考えてしまいます。
そのようなSystem.IO.AbstractionsとSystem.IO.Abstractions.TestingHelpersを使用することにより:
public class ManageFile {
private readonly IFileSystem _fileSystem;
public ManageFile(IFileSystem fileSystem){
_fileSystem = fileSystem;
}
public bool FileExists(string filePath){}
if(_fileSystem.File.Exists(filePath){
return true;
}
return false;
}
}
テストクラスでは、MockFileSystem()を使用してファイルをモックし、ManageFileを次のようにインスタンス化します。
var mockFileSysteme = new MockFileSystem();
var mockFileData = new MockFileData("File content");
mockFileSysteme.AddFile(mockFilePath, mockFileData );
var manageFile = new ManageFile(mockFileSysteme);
あなたはMicrosoft Fakesを使用してそれを行うことができますたとえば、既に凍結されているため、コードベースを変更する必要なく、。
最初にSystem.dllまたはその他のパッケージの偽のアセンブリを生成し、次に期待される戻り値を模擬します。
using Microsoft.QualityTools.Testing.Fakes;
...
using (ShimsContext.Create())
{
System.IO.Fakes.ShimFile.ExistsString = (p) => true;
System.IO.Fakes.ShimFile.ReadAllTextString = (p) => "your file content";
//Your methods to test
}
ファイルシステムをモックアップする方法がわかりません。あなたができることは、テストに必要な構造を持つフォルダなどを作成するテストフィクスチャのセットアップを書くことです。ティアダウンメソッドは、テストの実行後にクリーンアップします。
追加用に編集:これについてもう少し考えると、このタイプのメソッドをテストするためにファイルシステムを模擬したいとは思わないでしょう。特定のファイルが存在する場合にファイルシステムをモックしてtrueを返し、そのファイルが存在するかどうかを確認するメソッドのテストでそれを使用すると、ほとんど何もテストされません。ファイルシステムのモックが役立つのは、ファイルシステムに依存するメソッドをテストしたいが、ファイルシステムのアクティビティがテスト中のメソッドに不可欠ではなかった場合です。
特定の質問に答えるには:いいえ、ファイルI / O呼び出し(私が知っている)を模擬できるライブラリはありません。つまり、タイプを「適切に」ユニットテストするには、タイプを定義するときにこの制限を考慮する必要があります。
「適切な」単体テストの定義方法について簡単に説明します。ユニットテストでは、既知の入力が提供された期待される出力(例外、メソッドの呼び出しなど)が得られることを確認する必要があると思います。これにより、ユニットテスト条件を一連の入力または入力状態、あるいはその両方として設定できます。これを行うために見つけた最良の方法は、インターフェイスベースのサービスと依存性注入を使用することです。これにより、型の外部の各責任は、コンストラクターまたはプロパティを介して渡されるインターフェイスを介して提供されます。
これを念頭に置いて、あなたの質問に戻りましょう。mscorlibファイルシステムメソッドの単なるファサードIFileSystemService
であるFileSystemService
実装と共にインターフェイスを作成することにより、ファイルシステムコールを模倣しました。次に、コードIFileSystemService
ではmscorlibタイプではなくタイプを使用します。これによりFileSystemService
、アプリケーションの実行中に標準を接続したりIFileSystemService
、単体テストのモックを作成したりできます。アプリケーションコードは実行方法に関係なく同じですが、基盤となるインフラストラクチャにより、そのコードを簡単にテストできます。
mscorlibファイルシステムオブジェクトのラッパーを使用するのは面倒ですが、これらの特定のシナリオでは、テストが非常に簡単で信頼性が高くなるため、追加の作業を行う価値があります。
インターフェースを作成してテスト用にモックするのが、最もクリーンな方法です。ただし、代替手段として、Microsoft Molesフレームワークを確認することもできます。
一般的な解決策は、いくつかの抽象的なファイルシステムAPI(Apache Commons VFS for Javaなど)を使用することです。すべてのアプリケーションロジックはAPIを使用し、単体テストは、実際のファイルシステムをスタブ実装(メモリ内エミュレーションなど)で模擬できます。
C#の場合、同様のAPIが存在します。NI.Vfsは、Apache VFS V1に非常に似ています。これには、ローカルファイルシステムとメモリ内ファイルシステムの両方のデフォルト実装が含まれています(最後の実装は、ボックスからのユニットテストで使用できます)。