保存されたファイルを読み込んで解析することで、正しいデータが保存されているかどうかをテストできます。データを正しく解析できれば、「正しく保存」されているはずです。コードが実際にファイルをディスクに保存するかどうかを尋ねている場合、それはクラスではなく FileStream クラスの単体テストです。
ただし、モック ライブラリを使用してクラスの動作をテストする方が簡単です。これは、C# コミュニティで人気があると思われる 3 つのフレームワークの比較です。Rhino Mocks vs Moq vs NSubstitute . NUnit (ナゲットでも利用可能)もお勧めします。これは、優れたテスト フレームワークだからです。
モッキング フレームワークを使用する場合、クラスで使用できる「偽の」オブジェクトを作成します。これは、依存性注入 (つまり、クラスに依存性を注入する) を使用する必要があることも意味します。クラスの依存関係は、データベース アクセス クラスとファイル アクセス クラスのようです。それらをクラスに渡すことで、単一責任の原則にも従うことになります。簡単に言えば、1 つのクラスは 1 つのことだけを知っている必要があるということです。(たとえば、データベースへのアクセス方法やファイルへのアクセス方法を知っている必要はありません)
必要なものIDatabaseRepository
、IFileStorage
またはそれらの線に沿ったものに対して 2 つのインターフェイスを作成するだけです。次に、それらのインスタンスをクラスに注入します。単体テストを作成しているとき、これらは簡単にモックされます。たとえば、Rhino モックを使用すると、単体テストはこれに沿って調べることができます。
public interface IDatabaseProvider {
IEnumerable<Car> GetCars();
}
public interface IFileStorage {
string ReadText(string filepath);
void SaveText(string filepath, string content);
}
public class MyClass {
private readonly IDatabaseProvider dataProvider;
private readonly IFileStorage storage;
public MyClass(IDatabaseProvider dataProvider, IFileStorage storage) {
this.dataProvider = dataProvider;
this.storage = storage;
}
public void GenerateCarDetailsFile(IList<int> carIds, string location) {
var cars = dataProvider.GetCars().Query<Car>().Where(x => carIds.Contains(x.Id));
StringBuilder builder = new StringBuilder();
builder.AppendLine("Make, Model, Year");
foreach(var car in cars) {
builder.WriteLine("{0},{1},{2}", car.Make, car.Model, car.Year);
}
storage.SaveText(location, builder.ToString());
}
}
[Test]
public void GenerateCarDetailsSavesFile() {
// Arrange
var databaseReturnValue = new List<Car> { new Car() { Make = "ma", Model = "mo", Year = 1900 };
var location = "testpath.ext";
var ids = new List<int> { 1, 3, 6 };
var expectedOutput = "Make, Model, Year\r\nma,mo,1900";
var database = MockRepository.GenerateMock<IDatabaseProvider>();
var storage = MockRepository.GenerateMock<IFileStorage>();
database
.Stub(m => m.GetCars())
.Return(databaseReturnValue);
storage
.Expect(m => m.SaveText(Arg<string>.Is.Equal(location),
Arg<string>.Is.Equal(expectedOutput)));
MyClass testee = new MyClass(database, storage);
// Act
testee.GenerateCarDetailsFile(ids, location);
// Assert
storage.VerifyAllExpectations();
}
SaveText
クラスの動作と、IFileStorage
依存関係を呼び出す必要があるという事実をテストしています。依存性注入を使用し、すべての補助システムを抽象化することで、データベースにアクセスできない場合やファイル システムがいっぱいになった場合に失敗しないテストを作成できます (これらのイベントは別の単体テストになる可能性があることに注意してください)。
また、より移植性の高いクラスを作成します。これを別の方法でファイル システムにアクセスする別のプラットフォーム (.NET と Windows ストアなど) に移動File
するStorageFile
場合は、プラットフォーム固有のIFileStorage
実装を作成するだけです。
したがって、他のクラスの動作をテストしないでください。代わりに、依存関係に関してクラスの動作をテストしてください。次に、モックを使用して、テスト間で同じように機能する依存関係の動作をセットアップします。