【问题标题】:Mongodb unit testing in .NET.NET 中的 Mongodb 单元测试
【发布时间】:2012-09-30 01:23:04
【问题描述】:

我正在尝试做 tdd 并使用 mongodb 作为数据库。但我无法解决模拟 mongodb 的问题。是否有能力模拟 mongodb 以在 .NET 中进行单元测试?


更新

我发现非常好的解决方案阅读博客。 你可以找到它here:

【问题讨论】:

    标签: c# .net unit-testing mongodb mocking


    【解决方案1】:

    您应该在 MongoDB 之上模拟一个层,而不是模拟 MongoDB。

    您可能需要考虑一个接口,该接口公开您的存储库上的操作,这些操作与底层数据存储无关。例如,您可能需要一个抽象出Student 类型操作的接口,如下所示:

    public interface IStudentOperations
    {
        void Add(Student student);
    }
    

    当您创建其他依赖项时,您会注入上述接口的实例,或者您选择的任何更高级别的抽象。

    重点是,不要直接暴露MongoDB

    一旦你这样做了,你就可以模拟你创建的所有你想要的接口,有一个实现来测试模拟实现,然后一个实际的实现带有它自己的测试来验证实现上的操作是正确的,当底层使用 MongoDB 实现。

    虽然肯定是possible to mock most of MongoDB's classes (as the methods are virtual),但您获得了与持久性无关的好处;如果你想切换到 CouchDB 或 elasticsearch,你不必改变对这些接口的调用,你只需创建一个新的实现。


    因为you are trying to test the implementation of the repository,那你一般没问题,前面已经说了,MongoDB的大部分函数都是virtual,对大部分mocking库都很友好。

    也就是说,您必须确保将MongoDatabase 传递到您的存储库(而不是在存储库中创建它),以便在您的单元中测试,您可以创建适当的模拟,然后将其传递到您的存储库实现进行测试。

    【讨论】:

    • 虽然我同意 casperOne,但由于公共方法是虚拟的,因此可以使用大多数模拟框架模拟 MongoDB 驱动程序的类。
    • 我将使用存储库模式。所以我需要模拟 All、Save 和其他人。这就是为什么我需要模拟 mongo
    • @kfuglsang 更新了不直接模拟 MongoDB 的答案。
    • @F0rc0sigan 您是在测试存储库的实现,还是调用对存储库
    • @F0rc0sigan 抱歉,Stack Overflow 不是代码编写服务。你也没有指出你想模拟什么方法,你试过什么,或者你正在使用什么模拟库。甚至没有足够的信息来尝试给你一个样本。
    【解决方案2】:

    您需要一个存储库/DAL 层来隐藏实现细节。像这样的:

    public interface IDataContext<T>
    {
       // Query
       IList<T> GetAll<T>();
       IList<T> GetByCriteria<T>(Query query);
       T GetByID<T>(string id);
    
       // CUD
       void Add(T item);
       void Delete(T item);
       void Save(T item);
    }
    
    • 对于生产代码,在 C# 驱动的帮助下实现与 mongo db 操作的接口
    • 对于单元测试代码,使用内存集合模拟接口

    模拟添加/删除/保存看起来很简单,有趣的部分是查询功能。幸运的是,由于 mongo C# 驱动程序支持 LINQ 表达式,我们可以使用 LINQ 作为查询语言,而不是重新发明轮子。

    例如,生产代码可能如下所示:

    // collection is a MongoCollection<T> object
    var items = collection.AsQueryable().Where(...linq expression...);
    

    还有单元测试代码(如果你使用 Shim,MS 测试):

    using (ShimsContext.Create())
    {                  
        ShimLinqExtensionMethods.AsQueryableOf1MongoCollectionOfM0(
            (MongoCollection<T> x) => Fake_DB_Collection.AsQueryable());
        // After this, the above "collection.AsQueryable()" will be mocked as 
        // an in-memory collection, which can be any subclass of IEnumerable<T>             
    } 
    

    【讨论】:

    • GetByCriteria 应该返回 IQueryable 或 IEnumerable
    【解决方案3】:

    看到这个类似的问题:Mocking database in node.js?

    简而言之,模拟 MongoDB 不是正确的方法。模拟您的存储库足以测试您自己的单元,但如果您想确保正确使用它,或者如果您依赖唯一性约束等,您仍然需要针对 MongoDB 进行测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      • 1970-01-01
      • 2010-09-05
      • 1970-01-01
      • 2018-10-01
      相关资源
      最近更新 更多