0

EntityFrameworkEntityを取得してDTOオブジェクトに変換するメソッドがあります。このメソッドでは、スキップして返す関連アイテムの数を制限するパラメーターがあります。小さなデータセットでは、次のような単純なクエリがうまく機能しました。

var query = this.AccessLogs
    .Skip(skipRelated)
    .Take(takeRelated);

より大きなデータセットでは、これが実際にデータベースでSELECT *を実行し、場合によっては何百万もの関連レコードがあるため、多くの問題を引き起こすことがわかりました。この質問をした後、私はクエリを次のように変更しました。

var query = this.AccessLogs
    .CreateSourceQuery()
    .OrderBy(p => p.ID)
    .Skip(skipRelated)
    .Take(takeRelated);

これで統合テスト中に発生したパフォーマンスの問題は修正されましたが、これによりユニットテストのすべてが失敗します。これ.CreateSourceQuery()はnullを返し、次に.OrderBy()パラメーター名にArgumentNullExceptionを持つbarfsを返すためです:source。

戻るリポジトリがありIQueryable<T>、それを単体テストするための依存性注入の設定があるので、このように「テスト」データを設定しています。もともとは使っていたのですが、テスト用に使っているこの記事List<T>を見つけました。いずれにせよ、基になるコレクションにデータがある場合でも、への呼び出しはnullを返します。InMemoryObjectSet<T>.CreateSourceQuery()

IObjectSet<Parent> ret = new InMemoryObjectSet<Parent>();
var parent = new Parent();
parent.ID = 1;
parent.Name = "Name 1";
for(int i = 0; i < 5; i++)
{
    var ch = new Child();
    ch.ID = i;
    ch.ParentID = 1;
    ch.Property1 = "Name " + i.ToString();
    parent .Children.Add(ch);
}
ret.AddObject(parent);

.CreateSourceQuery()私の質問はこれです: nullを返さないように単体テストのテストデータを設定するにはどうすればよいですか?

4

1 に答える 1

1

あなたはしません。EF 関連のコードをテストする場合は、実際の EF と実際のデータベースを使用して行う必要があります。これを回避する方法はありません。これを回避しようとすると、アプリケーションをテストしないことになりますが、EF がどのように機能するかについての仮定が必要です。

あなたの場合、偽造できないのはなぜですか?CreateSourceQueryのメソッドでEntityCollectionあり、エンティティ コレクションは実際の ObjectContext に依存します。同時にEntityCollection封印されます。このメソッドは、パブリック インターフェイスでも使用できません。したがって、そのロジックを通常の単体テスト API に置き換える方法はありません。唯一のオプションは、メソッド呼び出しを他のものにリダイレクトできる、より高度なテクノロジーを使用することです (これは、商用の TypeMock Isolator および MS Moles によってのみ提供されます)。 => あなたが所有していないコードについての仮定をテストします。あらゆる種類の偽造は、テストが EF 関連のコード、クエリ、または永続性をテストしていない場合にのみ意味があります。そのようなものは、別の統合テストでカバーする必要があります。

それを避ける方法は?テストしたクラスで、新しいメソッドを作成します。

protected virtual IEnumerable<AcessLog> GetLogs(int skipRelated, int takeRelated)
{
     return this.AccessLogs.
                .CreateSourceQuery()
                .OrderBy(a => p.ID)
                .Skip(skipRelated)
                .Take(takeRelated);
}

GetLogsテストでは、元のクラスではなく、何らかの方法でメソッドをオーバーライドしてテストで期待するものを返す派生クラスを使用します。

ちょっと待って。内のロジックのテストをスキップしましGetLogsたね。はい、確かにそうでした。前述のように、このコードは単体テストできません。実際のデータベースを使用した個別の統合テストでカバーする必要がありますが、そのコードは単一のメソッドに分離されており、このメソッドに依存する他のすべてのロジックは、このメソッドを偽造することで単体テストできます。

で発生する可能性のあるすべての問題をカバーしているわけではありませんCreateSourceQuery。たとえば、リレーションが既に読み込まれている場合はどうなりますか? または、エンティティが何らかの理由で切り離された場合はどうなりますか? これらはテストが容易ではない副作用です。

于 2011-12-29T20:08:54.867 に答える