2011-08-11 138 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

我一直在使用從http://efmvc.codeplex.com的EF代碼優先+庫模式具有不同於你構建你的

我注意到的第一件事情就是你的工作單位是依賴於EF的方式一對夫婦的差異。工作EFMVC的單位根本就

public interface IUnitOfWork 
{ 
    void Commit(); 
} 

爲了避免追平了庫來EF,我們有

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的依賴。所以,現在不是嘲諷IFRSDbContextIDbSet S(的EntityFramework),你嘲笑其IQueryable S(System.Core程序)

編輯IRepository<T>:你的問題,它可能是這個樣子

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

謝謝。那麼我現在將我的IDatabaseFactory注入到我的構造函數中而不是IFRSDbContext中,還是將注入我的存儲庫或我的工作單元?對不起,我是新來的存儲庫/工作單元設計模式。 – shuniar

+0

不要對不起 - 這是SO的目的;)你是正確的,'RepositoryBase'被注入一個'IDatabaseFactory'。然後在你的服務層(或者任何消耗你的倉庫),你需要一個或多個'IRepository'和'IUnitOfWork'。不要忘記在您的服務操作中調用'_unitOfWork.Commit();'這些存儲庫不會爲您提供。 – kenwarner

+0

所以我不會將工作單元傳遞給我的業務對象來提交數據,但只能在調用之外提交數據?即上傳器。上傳(報告); unitOfWork.Commit();' – shuniar

相關問題