因为我想对我的代码进行单元测试,所以我在MVC4应用程序中实现了存储库模式。我设法创建了一个Context Interface,一个假的Context,并通过跟随System.Data.Entity.DbSet
代码使用this的假实现。
不幸的是,就像我面前的两张海报(here和here)一样,我无法模仿DbContext.Entry method
。我使用此方法更新代码中的数据库条目,如下所示:
DbContext.Entry(order).State = EntityState.Modified;
我还没有找到解决这个问题的方法,只有那些人说的话:
“这个代码的单元测试有什么意义?你伪造了Find 方法,那么你伪造DbEntityEntry并没有真正的逻辑 试验“。
或
在继续之前,请先阅读this以及所有相关问题。 (...)如果您想测试您的存储库,请创建与真实数据库对话的集成测试。
这一切都很好,但仍然没有回答这个问题。我阅读了批评,我仍然想要这个Entry方法,所以我将能够使用假上下文并在我的单元测试中使用模拟对象。当然我也会使用集成测试,但它们并不像某些快速单元测试那么快。
我尝试某些实现时收到的错误是Error 2 'Project.Models.Order' does not contain a definition for 'State' and no extension method 'State' accepting a first argument of type '[whatever return type I use]' could be found (are you missing a using directive or an assembly reference?)
我希望有人可以帮我制作一个虚假的DbContext.Entry方法。
答案 0 :(得分:36)
通过“添加更多级别的间接”找到答案here:
public void SetModified(object entity)
{
Entry(entity).State = EntityState.Modified;
}
并在我们的控制器中使用DbContext.SetModified(entity)
。
答案 1 :(得分:5)
为了解决这个问题,我添加了一个方法重载,并添加了一个过时的属性来查看原始方法的调用位置。
If Not myRecipients.ResolveAll Then
然后你可以 public virtual void Entry<TEntity>(TEntity entity, Action<DbEntityEntry<TEntity>> action) where TEntity : class
{
action(base.Entry(entity));
}
[Obsolete("Use overload for unit tests.")]
public new DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class
{
return base.Entry(entity);
/** or **/
throw new ApplicationException("Use overload for unit tests.");
}
答案 2 :(得分:2)
如何实现基于接口的存储库和工作单元以获取您所需的内容的示例:
public interface IRepository<T>
{
T FindSingle(Expression<Func<T, Boolean>> predicate, params Expression<Func<T, object>>[] includeExpressions);
void ProxyGenerationOn();
void ProxyGenerationOff();
void Detach(T entity);
void Add(T newEntity);
void Modify(T entity);
void Attach(T entity);
void Remove(T entity);
void SetCurrentValues(T modifiedEntity, T origEntity);
T GetById(int id);
T GetById(int id, bool sealOverride);
IQueryable<T> GetAll();
IQueryable<T> GetAll(bool sealOverride);
IQueryable<T> GetAll(string[] EagerLoadPaths);
IQueryable<T> Find(Expression<Func<T, Boolean>> predicate);
}
public interface IUnitOfWork : IDisposable
{
//repository implementations go here
bool SaveChanges()
}
注意上下文是如何被完全抽象掉的。您只需要在具体实现中担心它。
答案 3 :(得分:2)
您可以使用DbContext.Update(entity)
。就我而言,它可以正常工作,因为我嘲笑了DbContext
。
_dbContext.Update(entity);