创建一个假的DbContext

时间:2012-09-14 12:15:45

标签: asp.net-mvc entity-framework unit-testing

我正在使用EF创建一个MVC应用程序,并且目前使用了通用存储库模式,如下所示:Generic Repository Pattern。除了每个存储库创建一个新的上下文并在我的应用程序中使用两个或多个存储库这一事实之外,一切都很有效。当我使用StructureMap时,我添加了

x.For<IDbContext>().HttpContextScoped().Use(context => new MyContext());

其中IDbContext具有相应的方法,不再是通用的,而是通过构造函数传递。

问题来自于我必须测试的东西 - 我想创建一个内存存储(比db,自定义,易于控制的数据更快),例如HashTable或HashSet。我无法弄清楚的是如何制作一个虚假的IDbContext实现来从该HashTable中检索数据。作为参考,IDbContext看起来像这样(只有通用存储库中DbContext使用的方法):

    public interface IDbContext : IDisposable
    {
        IDbSet<TEntity> Set<TEntity>() where TEntity : class;
        DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
        int SaveChanges();
    }

在目前的情况下,我认为我犯了一个重大错误,因为创建一个虚假的上下文似乎并不是一个常规例程。关于如何改进我的应用程序的体系结构并使其更易于测试的任何建议都值得赞赏。

1 个答案:

答案 0 :(得分:0)

当我在过去做过这个时,我通常使用一个词典来保存我的测试数据:

public class FakeDb : IDbContext
{
    private Dictionary<Type, Object> _lists = new Dictionary<Type, Object>();
    public List<T> GetList<T>()
    {
        var type = typeof(T);
        if(!_lists.Contains(type))
        {
            _lists.Add(type, new List<T>());
        }
        return (List<T>)_lists[type];
    }

    ///
}

从更广泛的角度来看,通过将查询构建逻辑包装到individual classes rather than repository classes中,我获得了很多成功。