1

我一直在研究使用 EF 实现存储库模式的各种方法,特别是使用通用存储库。

我一直在尝试使用具有 IContext 属性的 IRepository,因此 IRepository 的任何实现之间的唯一区别就是上下文。我发现这很困难,以至于我放弃了“假上下文”方法,现在只在假存储库中有一个 List 字典作为我的“上下文”:

public Dictionary<Type, object> _sets = new Dictionary<Type, object>();

为了操纵它,会在假的时候做这样的事情:

public void Add<T>(T entity) where T : class
    {
        var set = _sets[typeof (T)] as IQueryable<T>;
        var updatedSet = set.ToList();
        updatedSet.Add(entity);
        _sets[typeof (T)] = updatedSet.AsQueryable<T>();
    }

在真正的存储库中,我可以使用:

void Add<T>(T entity)
    {
        Set<T>().Add(entity);
    }

在我的 Update 方法中,我必须有类似的不同实现来容纳继承 DbContext 的真实上下文,以及使用基于集合的方法的假。

这种方法让我很紧张。正如其他人在其他问题中提到的那样,现在我的存储库实现是如此不同,以至于我觉得我不能信任一个测试,直到它使用假的和真实的存储库运行。

我只是一个想太多的菜鸟吗?或者有没有更好的方法来实现一个更像 DbContext 的假上下文,所以我不必让如此截然不同的类实现存储库接口?

总结一下:我了解使用内存存储库进行测试的优势。我的问题是,当我必须对存储库进行两种不同的实现时,这是否意味着我做错了什么,或者这只是用假货进行测试的成本,如果逻辑测试通过,我应该'汗流这么多?

4

1 回答 1

0

以下是我们在我正在处理的项目中所做的:我们有一个围绕 EF 的存储库包装类,这样我们就可以在需要时在单元测试中使用模拟。我考虑过像您正在做的那样做一个内存存储库,但我最终决定反对它,因为我真的只需要它来进行查询。但是,由于 Linq To Entities 是 Linq to Objects 的子集。单元测试可能会通过,但集成测试会失败,因为您可能一直在使用不属于 Linq to Entities 的功能。如果我需要对该查询进行集成测试并且不能信任单元测试,那么两者都做是没有意义的。

对于单元测试,我只是模拟了存储库并验证了是否调用了适当的方法(插入或其他)。对于删除/插入/任何内容的集成测试,只需点击实际数据库即可。

对于实际查询,我只是做了集成测试。我将查询移至单独的函数。我的代码将调用该函数来检索查询结果,我可以单独对带有查询的函数进行集成测试,并对查询结果的处理进行单元测试。

我不知道这是否有意义,或者是否有更好的方法来做到这一点,但这就是我最终要做的。

或者,如果您想继续内存实现 ,我认为您应该能够执行以下操作:

只需有一个对象列表并使用 OfType 返回正确的类型:

public TEntity Get<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> where, params System.Linq.Expressions.Expression<Func<TEntity, object>>[] includeProperties) where TEntity : class
{
    return _repositories.OfType<TEntity>().AsQueryable().Where(where).FirstOrDefault();
}

public TEntity Insert<TEntity>(TEntity tEntity) where TEntity : class
{
    _repositories.Add(tEntity);
    return tEntity;
}
于 2013-02-05T21:18:56.473 回答