1

私は、特に汎用リポジトリを使用して、EF でリポジトリ パターンを実装するためのさまざまなアプローチを検討してきました。

IContext プロパティを持つ IRepository を使用しようとしていたため、IRepository の実装間の唯一の違いはコンテキストになります。「偽のコンテキスト」アプローチを放棄し、偽のリポジトリに「コンテキスト」としてリストの辞書を持っているだけで、これは十分に難しいことがわかりました。

public Dictionary<Type, object> _sets = new Dictionary<Type, object>();

そしてそれを操作するには、偽物で次のようにします:

public void Add<T>(T entity) where T : class
    {
        var set = _sets[typeof (T)] as IQueryable<T>;
        var updatedSet = set.ToList();
        updatedSet.Add(entity);
        _sets[typeof (T)] = updatedSet.AsQueryable<T>();
    }

実際のリポジトリでは、次を使用できます。

void Add<T>(T entity)
    {
        Set<T>().Add(entity);
    }

私の Update メソッドでは、DbContext を継承する実際のコンテキストと、コレクション ベースのアプローチを使用する偽物に対応するために、同様に異なる実装が必要になります。

このアプローチは私を緊張させます。他の質問で他の人が言及しているように、私のリポジトリの実装は非常に異なっているため、偽のリポジトリと実際のリポジトリの両方で実行されるまで、テストを信頼できないと感じています。

私はこれを考えすぎているだけの初心者ですか?または、DbContext のように動作する偽のコンテキストを実装するより良い方法があるので、リポジトリ インターフェイスを実装するこのような大幅に異なるクラスを使用する必要はありませんか?

要約すると、インメモリ リポジトリを使用したテストの利点を理解しています。私の質問は、これほど異なるリポジトリの 2 つの実装を作成する必要がある場合、それは私が何か間違ったことをしていることを意味するのでしょうか、それともこれは偽物を使用したテストのコストにすぎないのでしょうか。ロジック テストに合格した場合は、そうすべきです。そんなに汗をかくの?

4

1 に答える 1

0

私が取り組んでいるプロジェクトで行ったことは次のとおりです。必要なときに単体テストでモックを使用できるように、EF の周りにリポジトリ ラッパー クラスがあります。あなたがやっているようにメモリ内リポジトリを実行することを検討しましたが、実際にはクエリを実行するためだけに必要だったので、最終的には反対しました。ただし、Linq To Entities は Linq to Objects のサブセットであるためです。単体テストに合格しても、Linq to Entities の一部ではない機能を使用していた可能性があるため、統合テストに失敗することがあります。そのクエリを統合テストする必要があり、単体テストを信頼できない場合、両方を行う意味がないと感じました。

単体テストでは、リポジトリのモックを作成し、適切なメソッド (Insert など) が呼び出されたことを確認しました。削除/挿入/その他の統合テストについては、実際のデータベースをヒットするだけです。

実際のクエリについては、統合テストを行っただけです。クエリを別の関数に移動しました。私のコードはその関数を呼び出してクエリ結果を取得し、関数とクエリを個別に統合テストし、クエリ結果の処理を単体テストすることができました。

それが理にかなっているか、それを行うためのより良い方法があるかどうかはわかりませんが、それが私がやったことです.

または、インメモリ実装を続行したい場合 は、次のことができるはずです。

オブジェクトのリストを取得し、OfType を使用して正しい型を返すだけです。

public TEntity Get<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> where, params System.Linq.Expressions.Expression<Func<TEntity, object>>[] includeProperties) where TEntity : class
{
    return _repositories.OfType<TEntity>().AsQueryable().Where(where).FirstOrDefault();
}

public TEntity Insert<TEntity>(TEntity tEntity) where TEntity : class
{
    _repositories.Add(tEntity);
    return tEntity;
}
于 2013-02-05T21:18:56.473 に答える