【问题标题】:Testing a fake repository测试假存储库
【发布时间】:2013-01-20 22:17:16
【问题描述】:

我一直在研究使用 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 的假上下文,这样我就不必让如此截然不同的类实现存储库接口?

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

【问题讨论】:

    标签: entity-framework tdd repository-pattern


    【解决方案1】:

    这是我们在我正在处理的项目中所做的:我们有一个围绕 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;
    }
    

    【讨论】:

    • 谢谢。我可能会开始嘲笑,但我试图在每一步都弄脏我的手,所以现在我只是坚持使用内存中的方法来处理假数据,使用 EF 上下文来处理真实数据。我昨天尝试了您的方法,但经过几次失败的测试才意识到我无法添加到类型为 IQueryable 的集合中。不过,您的评论确实使我意识到我不需要将集合添加为 IQueryable。现在,我只需将集合添加为列表 - 使 Add/Update/Delete 更清晰,并且当我需要在测试中查询时,我可以使用 QuerySet 方法将列表返回为 IQueryable。
    猜你喜欢
    • 2010-09-29
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 2016-07-28
    • 1970-01-01
    • 2014-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多