0

私はNHibernateを使用しており、すべての基底NHibernateRepositoryクラスから継承する多くのリポジトリを持っています。ここに私のリポジトリの1つである:構造マップを使用して基本クラスをモックする方法は?

public class StaffRepository : NHibernateRepository<IStaff>, 
{ 
    public IEnumerable<IStaff> GetBySiteRegionAndMonth(int siteId, int regionId, DateTime firstOfMonth) 
    { 
     return Repository.Where(ab => ab.SiteId == siteId && ab.WorkDate >= firstOfMonth && ab.WorkDate < firstOfMonth.AddMonths(1)); 
    } 
} 

とベースクラス:

public class NHibernateRepository<TEntity> : IRepository<TEntity> where TEntity : IEntity 
{ 
    protected ISession session; 

    public NHibernateRepository() 
    { 
     this.session = new SessionCache().GetSession(); 
    } 

    public IQueryable<TEntity> Query 
    { 
     get 
     { 
      return session.Query<TEntity>(); 
     } 
    } 

    // Add 
    public void Add(TEntity entity) 
    { 
     session.Save(entity); 
    } 

    // GetById 
    public TEntity GetById(int id) 
    { 
     // return session.Load<TEntity>(id); 
     return this.Query.SingleOrDefault(e => e.Id == id); 
    } 
} 

私は今、本当のデータベースにアクセスしませんテストクラスを使用して、基本クラスNHibernateRepositoryにモックしようとしています、代わりに静的リストを使用します。ここではテストクラスの私の登録が私の構造マップコンテナである:

x.For(typeof(IRepository<>)).Use(typeof(TestNHibernateRepository<>)); 

私の問題は、実際のNHibernateRepositoryはまだテストで使用されていること、です。

x.For<IStaffRepository>().Singleton().Use<StaffRepository>(); 

すべて私の他のテストクラスが罰金を注入されているが、私はそれが継承されたクラスであるとして、これは問題にされていると思う:私は私の登録につきとして本当のStaffRepositoryを使用しています。

NHibernateRepositoryではなく、私のStaffRepositoryがTestNHibernateRepositoryを使用していることを確認するにはどうすればよいですか?

答えて

3

偽の実装を作成するのは簡単ですが、ユニットテストは非常に信頼性が低くなります。その場合、IQueryable<T>が公開され、その結果、tight couplingが発生し、常に特定の実装がリークします。

これは、あなたのユニットテストでIQueryable<T>上のオブジェクトの実装にLINQを使用している場合NHibernateのクエリプロバイダを使用しているとき、彼らは非常によく失敗するかもしれないが、あなたはIQueryable<T>上書きほぼすべてのLINQクエリは常に、成功することを意味します。

代わりに、あなたは本当のデータベースとの通信ではなく、メモリ内のスタンドインを意味統合テストを、使用してIRepository<T>に依存するクラスをテストする必要があります。単位テストは異なるレベルで行う必要があります。

IQueryable<T>がインターフェイスでも、実際には抽象化ではありません。少なくとも、それはLeaky Abstractionです。 a Dependency Inversion Principle violation。代わりにIQueryable<T>がデータアクセスレイヤー内でのみ使用されるようにする必要があります。

クエリオブジェクト(データ)がコアレイヤの一部であり、そのハンドラ(O/RMをIQueryable<T>)は、データアクセスレイヤの一部です。これらのハンドラを統合テストすると、それらのハンドラのコンシューマは再びユニットテストが可能になります。

関連する問題