2011-08-11 7 views
1

現在のプロジェクトで自分のDALにEntity Framework 4.1を使用していますが、moqでエンティティをモックしながらビジネスオブジェクトを単体テストしようとしています。EF 4.1 :: Moq&NUnitによるテスト

私はまたここで、各エンティティのリポジトリを持って仕事

public interface IFRSDbContext 
{ 
    IDbSet<Category> Categories { get; set; } 
    IDbSet<Cell> Cells { get; set; } 
    IDbSet<DealSummary> DealSummaries { get; set; } 
    IDbSet<DealSummaryDetail> DealSummaryDetails { get; set; } 
    IDbSet<Node> Nodes { get; set; } 
    IDbSet<Rto> Rtos { get; set; } 
    IDbSet<Sheet> Sheets { get; set; } 
    IDbSet<Version> Versions { get; set; } 
    IDbSet<VersionMapping> VersionMappings { get; set; } 

    DbEntityEntry Entry(object entity); 
    DbSet<TEntity> Set<TEntity>() where TEntity : class; 
    int SaveChanges(); 
} 

だけでなく、一般的なリポジトリ

public abstract class Repository<TEntity> where TEntity : class 
{ 
    protected IFRSDbContext DbContext; 

    protected Repository(IFRSDbContext context) 
    { 
     DbContext = context; 
    } 


    public virtual TEntity GetById(object id) 
    { 
     return DbContext.Set<TEntity>().Find(id); 
    } 


    public virtual void Insert(TEntity entity) 
    { 
     DbContext.Set<TEntity>().Add(entity); 
    } 


    public virtual void Delete(object id) 
    { 
     var entityToDelete = DbContext.Set<TEntity>().Find(id); 
     Delete(entityToDelete); 
    } 


    public virtual void Delete(TEntity entityToDelete) 
    { 
     DbContext.Set<TEntity>().Remove(entityToDelete); 
    } 


    public abstract void Update(TEntity entityToUpdate); 
} 

の一般的な単位を作成している例を示します。

public class DealSummaryRepository : Repository<DealSummary> 
{ 
    public DealSummaryRepository(IFRSDbContext context) : base(context) { } 


    public virtual DealSummary GetByFileName(string fileName) 
    { 
     return DbContext.Set<DealSummary>().FirstOrDefault(d => d.FileName == fileName); 
    } 


    public override void Update(DealSummary entityToUpdate) 
    { 
     var existingDealSummary = GetByFileName(entityToUpdate.FileName); 

     if (existingDealSummary == null) 
     { 
      var message = string.Format(@"Error :: Cannot update Deal Summary '{0}' because it does not exist 
             in the database.", entityToUpdate.FileName); 

      throw new Exception(message); 
     } 

     existingDealSummary.DateModified = DateTime.Now; 
     existingDealSummary.StartDate = entityToUpdate.StartDate; 
     existingDealSummary.EndDate = entityToUpdate.EndDate; 
     existingDealSummary.DueDate = entityToUpdate.DueDate; 
     existingDealSummary.WasWon = entityToUpdate.WasWon; 
     existingDealSummary.UploadedBy = entityToUpdate.UploadedBy; 

     if (existingDealSummary.Details != null) 
      existingDealSummary.Details.Clear(); 

     existingDealSummary.Details = entityToUpdate.Details; 
    } 
} 

私が持っている質問は、IDbSetオブジェクトを汎用リポジトリとして実装する方法ですoryを継承し、それを継承するか、私の作業単位にリポジトリを格納し、リポジトリ内にIDbSetを実装する必要がありますか?リポジトリ内でIDbSetを実装する際に唯一の問題は、リポジトリがEFに依存していることです。

どのような疑念やベストプラクティスにも大変感謝します。エンティティフレームワーク/データベースに依存せずにテストできるように、エンティティを擬似的にするための最も簡単なアプローチを取ろうとしています。

答えて

3

私はあなたが私が気づい

まず最初は、作業単位がEFに結び付けられているあなたを構築してきた方法からカップルの違いがありhttp://efmvc.codeplex.comからEFコードファースト+リポジトリパターンを使用してきました。仕事のEFMVCの単位は、EFにリポジトリを拘束しないようにするには、単に

public interface IUnitOfWork 
{ 
    void Commit(); 
} 

で、我々は

public interface IRepository<T> where T : class 
{ 
    void Add(T entity); 
    void Update(T entity); 
    void Delete(T entity); 
    void Delete(Expression<Func<T, bool>> where); 
    T GetById(long Id); 
    T GetById(string Id); 
    T Get(Expression<Func<T, bool>> where); 
    IQueryable<T> GetAll(); 
    IQueryable<T> GetMany(Expression<Func<T, bool>> where); 
} 

IRepository<T>の私達の実装を持つEFへの依存性を必要とするものです。あなたの質問に、それはこの

public class Uploader : IUploader 
{ 
    private readonly IReportRepository _reportRepository; 
    private readonly IUnitOfWork _unitOfWork; 

    public Uploader(IReportRepository reportRepository, IUnitOfWork unitOfWork) 
    { 
     _reportRepository = reportRepository; 
     _unitOfWork = unitOfWork; 
    } 

    public void Upload(Report report) 
    { 
     _reportRepository.Add(report); 
     _unitOfWork.Commit(); 
    } 

} 
+0

おかげで次のようになります。だから今の代わりにそのIDbSet S(EntityFramework)とIFRSDbContextをからかっ、あなたはそのIQueryable S(System.Core)

EDITでIRepository<T>を模擬します。 IFRSDbContextの代わりにIDatabaseFactoryをコンストラクタに挿入するか、リポジトリまたは作業ユニットを挿入しますか?申し訳ありません。私はリポジトリ/作業単位設計パターンの初心者です。 – shuniar

+0

ごめんなさい - これはSOのためです;)あなたは正しいです、 'RepositoryBase'は' IDatabaseFactory'で注入されます。次に、あなたのサービス層(またはあなたのリポジトリを消費しているもの)に、1つまたは複数の 'IRepository'と' IUnitOfWork'が必要になります。あなたのサービス操作で '_unitOfWork.Commit();'を呼び出すことを忘れないでください。リポジトリはあなたのためにコミットしません。 – kenwarner

+0

私はデータをコミットするためにユニットオブジェクトを自分のビジネスオブジェクトに渡すことはしませんが、それらの呼び出しの外でのみコミットしますか?すなわち、 'uploader.Upload(report); unitOfWork.Commit(); ' – shuniar

関連する問題