How to fake DbContext.Entry method in Entity Framework with repository pattern
An example of how to implement Interface based repositories and unit of work to get what you are after:
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()
}
Notice how the context is completely abstracted away. You only need to worry about it in the concrete implementations.
To get around this I added a method overload, and added an obsolete attribute to see where the original method was being called.
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.");
}
then you can DbContext.Entry(order, ent => ent.State = EntityState.Modified;
Found the answer here by "adding additional level of indirection" we get:
public virtual void SetModified(object entity)
{
Entry(entity).State = EntityState.Modified;
}
and use DbContext.SetModified(entity)
in our controller.
mockContext.Setup(c => c.SetModified(It.IsAny()));