我在我当前的项目中使用Entity Framework 4.1作为我的DAL,现在我正在尝试使用moq模拟我的实体时对我的业务对象进行单元测试。
我创建了一个通用的工作单元
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对象实现为我的通用存储库并继承...或者我应该在我的工作单元中包含我的存储库,并在存储库中实现IDbSet?我在存储库中实现IDbSet的唯一问题是我的存储库依赖于EF。
任何建议/最佳实践将不胜感激。我试图采用最简单的方法使我的实体可以模拟,所以我可以测试没有依赖实体框架/我的数据库。
答案 0 :(得分:3)
我一直在使用http://efmvc.codeplex.com中的EF Code First + Repositories模式,这与您构建自己的方式有所不同
我注意到的第一件事是你的工作单元与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。所以现在不是使用IFRSDbContext
s(EntityFramework)模仿IDbSet
,而是使用IRepository<T>
s(System.Core)模拟IQueryable
编辑:对于你的问题,它可能看起来像这样
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();
}
}