Entity Frameworkを使用して構築されたエンティティをテストします。私の懸念は、Entity Frameworkを使用することは、データソースを直接操作することを意味することです。 Entity Frameworkベースのコンポーネントを単体テストする方法はありますか?
Entity Framework 4の場合、これは有望に見えます。 Testability and Entity Framework 4.
どうやらそれは非常に難しいです。エリックがここに弁明します- TDDおよびADO.NET Entity Framework
安価なアプローチは、実際のデータベースと同じ構造を持つデータベースファイルをセットアップし、それを指すように単体テスト構成で接続文字列を設定することです。データベースには、実際のテーブルにあるすべてのテーブルが必要ではありません。単体テストに必要なものだけです。
欠点は、単体テストが実行中および実行中に相互に影響を与えないように、データベースの状態を管理する必要があることです。
このアプローチは、実際のテストDBと単体テストDBの両方がSQL Expressを使用する場合に機能することを知っていますが、完全なSQL DBに対するSqlExpress DBのスタブについては知りません。
これは技術的には統合テストですが、コードをリファクタリングしたり、モックフレームワークを学習したりするよりも安くなる可能性があります。
実際の接続文字列の例:
<add name="DrinksEntities"
connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient
;provider connection string="Data Source=localhost\sqlexpress;Initial Catalog=Drinks2;Integrated Security=True;MultipleActiveResultSets=True;Application Name=EntityFramework""
providerName="System.Data.EntityClient" />
接続文字列をテストするユニットの例:
<add name="DrinksEntities"
connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient
;provider connection string="Data Source=.\SQLEXPRESS;attachdbfilename=|DataDirectory|\Inventory.mdf;Integrated Security=True;user instance=True;MultipleActiveResultSets=True;Application Name=EntityFramework""
providerName="System.Data.EntityClient" />
これに関する別の情報を共有したいと思います。 TypeMock Isolatorを使用して、Entity Frameworkベースのコンポーネントとアプリケーションをテストすることもできました。ただし、商用です。
この投稿をご覧ください: TypeMock Isolatorを使用したEntity Frameworkユニットテストの紹介
実際のデータにヒットするのではなく、モックフレームワークを使用してモック値を取得する必要があります。いくつかのモックフレームワークのリストと、開始に役立ついくつかのスクリーンキャストへのリンクを次に示します。
開始方法に関するスクリーンキャストは次のとおりです。
Entity Frameworkのバージョン1がいくつかの主要なソフトウェア設計原則に違反しているという事実により、アプリケーションでTDDを使用するときにTDDを適用する方法は実際にはありません。あなたがすぐに解決策を探しているなら、私の研究はNHibernateを指しています。単体テストを念頭に置いて設計されました。
ただし、待つことができる場合は、Entity Frameworkの次のリリースへの期待があります。 Entity Framework 4.0を使用したテスト駆動開発のウォークスルー
例は非常に単純化されている可能性がありますが、この問題に対する可能な解決策を議論しようとしました。それは懸念と親愛なる友人依存性注入の分離を伴います。
詳細が必要な場合はご連絡ください。
私は同意します、モックフレームワークはあなたが求めているものです。データソースから取得されない「模擬」オブジェクトを作成し、そのオブジェクトのデータをテストします。私は個人的にMoqで作業してきましたが、気に入っています。Rhinomocksやその他のものもあります。
これに多くのフラストレーションを感じた後、私は最終的に問題の少なくとも一部について満足できる解決策を手に入れました。
まず、次のようなリポジトリインターフェイスを使用します。
public interface IRepository
{
IQueryable<T> GetObjectSet<T>();
}
これを使用して、メモリ内コレクションまたは実際のDBバックアップコレクションを返すことができます。次に、次のようなインターフェイスを持つクエリオブジェクトにクエリをカプセル化します。
public interface IQuery<T>
{
IQueryable<T> DoQuery(IQueryable<T> collection);
}
次に、ユニットテストを2つのグループに分けます。最初のグループは、クエリが有効であることをテストします。次のようにしてください:
[TestMethod]
public void TestQueryFoo()
{
using(var repo = new SqlRepository("bogus connection string"))
{
var query = new FooQuery(); // implements IQuery<Foo>
var result = query.DoQuery(repo.GetObjectSet<Foo>()); // as long as we don't enumerate the IQueryable EF won't notice that the connection string is bogus
var sqlString = ((System.Data.Objects.ObjectQuery)query).ToTraceString(); // This will throw if the query can't be compiled to SQL
}
}
ユニットテストの2番目のセットでは、SQLコンパイルのステップを心配することなく、ビジネスロジックを自由にテストできます。
想像力の広がりによって完全ではなく、トリガーが実行されないことは明らかであり、DBに実装された制約に違反する可能性があります。そのため、エンドツーエンドの統合テストが依然として必要ですが、単純な単体テストで実行時に発生する最も一般的な問題がIMOであるかを把握することが可能です。
作業ユニットパターン+インメモリデータベース+偽EF dbContextを自動的に生成するt4コード生成の集合体を以下に示します。
http://mockingcompetence.wordpress.com/2013/05/20/fakingefdatacontext/
この時点で実際のEF db接続を正確に複製する場合、いくつかの問題(無効なlinq to EFクエリおよびFK強制なし)があります。
ただし、ユニットテストを迅速に実行するためのメモリ内コンテキストは、TDDまたは他の種類のユニットテスト中心のアプローチを実行するためにほぼ不可欠です。
さらに多くの問題を把握するにつれて、上記のリンクの更新を投稿します。
BookLibraryWPF Application Framework(WAF)プロジェクトのサンプルアプリケーションは、Entity Frameworkベースの方法を示していますアプリケーションは単体テストが可能です。
インメモリデータベースを使用して、Entity Frameworkモデルをテストできます。詳細は here をご覧ください