我在实体框架5中使用了ASP.NET MVC 4,我有模型类和实体地图来将现有表映射到这些模型类。所有这些都是很好的设置和工作的伟大。
现在我想嘲笑这个。我创建了工作单元( Unit Of Work ),它采用了DataContext,并使用了一个通用存储库。在此基础上,我构建了能够同时从多个存储库获取数据的服务,并且只需要拥有DataContext的一个实例。这也很好用。
现在的问题是:我想用模拟数据来测试服务。当我创建工作单元实例时,我希望能够插入一个被模拟的DataContext,而不是真正的DataContext。
我试图创建一个IContext接口,让真正的和模拟的DataContext实现它,但是DbSet遇到了问题。我试图使用IDbSet并创建一个FakeDbSet,但没有成功。我还在互联网上读到,用IDbSet来嘲弄上下文并使用FakeDbSet是一种糟糕的方法。
你知道什么是实现这一目标的最佳方式吗?我现在拥有的是我想要保持的行为,但我真的希望能够模拟来自DataContext中的Model类的数据。
我知道实体框架已经提供了工作行为单元,您不需要在此基础上添加额外的行为。但是我想把它封装在另一个类中,它跟踪所有的存储库(称为UnitOfWork类)。
编辑:--我写了两篇文章,解释了我使用LINQ和实体框架的解决方案。
http://gaui.is/how-to-mock-the-datacontext-linq/
http://gaui.is/how-to-mock-the-datacontext-entity-framework/
这是我的密码:
IRepository.cs
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
T GetById(long Id);
IEnumerable<T> All();
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
}IUnitOfWork.cs
public interface IUnitOfWork : IDisposable
{
IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
void Save();
}Repository.cs
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDbContext _context;
private readonly IDbSet<T> _dbset;
public Repository(IDbContext context)
{
_context = context;
_dbset = context.Set<T>();
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
var entry = _context.Entry(entity);
entry.State = System.Data.EntityState.Deleted;
}
public virtual void Update(T entity)
{
var entry = _context.Entry(entity);
_dbset.Attach(entity);
entry.State = System.Data.EntityState.Modified;
}
public virtual T GetById(long id)
{
return _dbset.Find(id);
}
public virtual IEnumerable<T> All()
{
return _dbset;
}
public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return _dbset.Where(predicate);
}
}UnitOfWork.cs
public class UnitOfWork<TContext> : IUnitOfWork where TContext : IDbContext, new()
{
private readonly IDbContext _ctx;
private Dictionary<Type, object> _repositories;
private bool _disposed;
public UnitOfWork()
{
_ctx = new TContext();
_repositories = new Dictionary<Type, object>();
_disposed = false;
}
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
if (_repositories.Keys.Contains(typeof(TEntity)))
return _repositories[typeof(TEntity)] as IRepository<TEntity>;
var repository = new Repository<TEntity>(_ctx);
_repositories.Add(typeof(TEntity), repository);
return repository;
}
public void Save()
{
_ctx.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this._disposed)
{
if (disposing)
{
_ctx.Dispose();
}
this._disposed = true;
}
}
}ExampleService.cs
public class ExampleService
{
private IRepository<Example> m_repo;
public ExampleService(IUnitOfWork uow)
{
m_repo = uow.GetRepository<Example>();
}
public void Add(Example Example)
{
m_repo.Add(Example);
}
public IEnumerable<Example> getAll()
{
return m_repo.All();
}
}ExampleController.cs
public IEnumerable<Example> GetAll()
{
// Create Unit Of Work object
IUnitOfWork uow = new UnitOfWork<AppDataContext>();
// Create Service with Unit Of Work attached to the DataContext
ExampleService service = new ExampleService(uow);
return service.getAll();
}发布于 2013-05-23 14:58:14
您的ExampleService类需要IUnitOfWork,这意味着您只需要另一个IUnitOfWork,即Mock,其GetRepository()方法将返回IRepository Mock。
例如(不是真正的模拟存根,而是内存存根):
public InMemoryRepository<T> : IRepository<T> where T : class
{
........
}
public InMemoryUnitOfWork : IUnitOfWork
{
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
return new InMemoryRepository<TEntity>();
}
}然后:
public IEnumerable<Example> GetAll()
{
// Create Unit Of Work object
IUnitOfWork uow = new InMemoryUnitOfWork();
// Create Service with Unit Of Work
ExampleService service = new ExampleService(uow);
return service.getAll();
}发布于 2013-12-28 01:05:15
https://stackoverflow.com/questions/16716527
复制相似问题