私は単体テストと TDD に少し慣れていないので、この投稿は議論のきっかけとなることを目的としています。
私は現在、いくつかのデータベースとやり取りする .NET プロセスの単体テストをいくつか作成しており、テスト内のさまざまなエッジ ケースをカバーするためにモック データベース コンテキストを使用し、プログラム自体の例外処理を検証しています。そうは言っても、私の単体テストの中には有効なデータを使用するものもあれば、そうでないものもあります。
有効な/偽のデータをモック データベース コンテキストに追加する際の推奨されるベスト プラクティスに関するフィードバックを探しています。人々がこれをさまざまな方法で行うのを見てきました (例: リポジトリ パターンを実装する、モック データを .csv ファイルに追加してプロジェクトの一部にするなど...)。
現在、ターゲット DBSurvey
のテーブルにオブジェクトを追加するためにリポジトリ パターンを使用することを考えています。Surveys
まず、私はインターフェースを持っています:
public interface ISurveyRepository
{
IQueryable<Survey> SurveySeries { get; }
}
これは、単体テストで必要に応じて、モック/有効なデータ リポジトリの両方に実装されます。
class FakeSurveyRepository : ISurveyRepository
{
private static IQueryable<Survey> fakeSurveySeries = new List<Survey> {
new Survey { id = 1, SurveyName="NotValid1", SurveyData="<data>fake</data>"},
new Survey { id = 2, SurveyName="NotValid2", SurveyData="<data>super fake</data>"},
.........,
new Survey {id = 10, SurveyName="NotValid10", SurveyData="<data>the fakest</data>" }
}.AsQueryable();
public IQueryable<Survey> SurveySeries
{
get { return fakeSurveySeries; }
}
}
// RealSurveyRepository : ISurveyRepository is similar to this, but with "good" data
次に、コンストラクターでシリーズへの参照を渡すことにより、このデータを偽/有効なデータとして消費するクラスを作成します。
public class SurveySeriesProcessor
{
private ISurveyRepository surveyRepository;
public SurveySeriesProcessor( ISurveyRepository surveyRepository )
{
this.surveyRepository = surveyRepository;
}
public IQueryable<Survey> GetSurveys()
{
return surveyRepository.SurveySeries
}
}
そして、次のようなテストでこれらのオブジェクトを使用してアプローチできます。
[TestClass]
public class SurveyTests
{
[TestMethod]
WhenInvalidSurveysFound_SurveyCopierThrowsInvalidSurveyDataErrorForEach()
{
// create mocking DB context and add fake data
var contextFactory = new ContextFactory( ContextType.Mocking );
var surveySeriesProcessor = new SurveySeriesProcessor( new FakeSurveyRepository() );
foreach(Survey surveyRecord in surveySeriesProcessor.GetSurveys() )
{
contextFactory.TargetDBContext.Surveys.AddObject( surveyRecord );
}
// instantiate object being tested and run it against fake test data
var testSurveyCopier = new SurveyCopier( contextFactory );
testSurveyCopier.Start();
// test behavior
List<ErrorMessage> errors = testSurveyCopier.ErrorMessages;
errors.Count.ShouldEqual( surveySeriesProcessor.GetSurveys().Count );
foreach(ErrorMessage errMsg in errors)
{
errMsg.ErrorCode.ShouldEqual(ErrorMessage.ErrorMessageCode.InvalidSurveyData);
}
}
}
ISurveyRepository
注: 提供されているサンプル コードでは、実装するクラスがシリーズを として返す必要は必ずしもないことを認識していますIQueryable<Survey>
(それらは である可能性が非常に高いですList<Survey>
)。ただし、将来的にはインターフェイスとこれらのクラスの機能を拡張して、LINQ クエリに追加された特定の基準に基づいて偽/有効なシリーズを除外する予定ですIQueryable<>
。これは、私が考えていることの基本原則を伝えるために設計されたモックアップ コードです。
これらすべてを念頭に置いて、私が求めているのは次のとおりです。
- そのようなシナリオで私が取ることができる代替アプローチに関して何か提案はありますか?
- 過去にどのような方法を採用してきましたか。その中で気に入った/気に入らなかった点は何ですか? 最も維持しやすいのはどれでしたか?
- 私が投稿した内容を踏まえて、単体テストに対する私の一般的なアプローチに欠陥があることに気づきましたか? 簡潔でエレガントで的を射たものではなく、あまりにも多くの領域をカバーしようとする単体テストを書いているように感じることがあります。
これは、ある程度オープンな議論になることを意図しています。これは私が今までに書いた最初の単体テストのセットであることを覚えておいてください (ただし、この件に関するかなりの量の文献を読みました)。