18

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


更新

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

4

3 回答 3

15

与其模拟 MongoDB,不如模拟 MongoDB之上的一个层。

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

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

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

关键是,不要直接暴露 MongoDB 。

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

虽然绝对可以模拟 MongoDB 的大多数类(就像方法一样virtual,但您获得了与持久性无关的好处;如果你想切换到 CouchDB 或 elasticsearch,你不必改变对这些接口的调用,你只需创建一个新的实现。


因为您正在尝试测试存储库的实现,所以您通常没问题,如前所述,MongoDB 的大部分功能都是virtual,这对大多数模拟库都很友好。

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

于 2012-10-09T16:49:07.557 回答
3

You need a repository/DAL layer to hide implementation details. Something like this:

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);
}
  • For production code, implement the interface with mongo db operations with the assistance of C# driver
  • For unit test codes, mock the interface with an in-memory collection

It looks straightforward to mock Add/Delete/Save, and the intersting part is query function. Fortunately, since mongo C# driver supports LINQ expressions, we can use LINQ as the query language rather than reinventing the wheels.

For example, the production code may look like:

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

And unit test code (if you go with Shim, MS test):

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>             
} 
于 2014-06-11T11:29:51.683 回答
1

看到这个类似的问题:在 node.js 中模拟数据库?

In short, mocking MongoDB isn't the right approach. Mocking your repository is adequate for testing your own units, but you'll still need to test against MongoDB if you want to make sure that you're using it correctly, or if you are relying on uniqueness constraints etc.

于 2012-10-09T16:55:09.273 回答