Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# NET中的Mongodb单元测试_C#_.net_Unit Testing_Mongodb_Mocking - Fatal编程技术网

C# NET中的Mongodb单元测试

C# NET中的Mongodb单元测试,c#,.net,unit-testing,mongodb,mocking,C#,.net,Unit Testing,Mongodb,Mocking,我正在尝试使用tdd和mongodb作为数据库。但我无法解决嘲笑mongodb的问题。有没有能力在.NET中模拟mongodb进行单元测试 更新 我发现读博客很好的解决方案。 您可以找到它:您不应该模拟MongoDB,而应该模拟MongoDB之上的一个层 您可能需要考虑一个接口,该接口公开了对基础数据存储区不可知的存储库上的操作。例如,您可能需要一个接口来抽象出Student类型上的操作,如下所示: public interface IStudentOperations { void

我正在尝试使用tdd和mongodb作为数据库。但我无法解决嘲笑mongodb的问题。有没有能力在.NET中模拟mongodb进行单元测试


更新

我发现读博客很好的解决方案。
您可以找到它:

您不应该模拟MongoDB,而应该模拟MongoDB之上的一个层

您可能需要考虑一个接口,该接口公开了对基础数据存储区不可知的存储库上的操作。例如,您可能需要一个接口来抽象出

Student
类型上的操作,如下所示:

public interface IStudentOperations
{
    void Add(Student student);
}
当您创建其他依赖项时,您将注入上述接口的实例,或者您选择的更高级别的抽象

关键是,不要直接公开MongoDB

一旦您这样做了,您就可以对您创建的所有接口进行模拟,让一个实现针对模拟实现进行测试,然后是一个实际的实现,该实现具有自己的测试,以验证当底层实现使用MongoDB时,实现上的操作是否正确

虽然这是肯定的,但你获得了持久性不可知论的好处;如果您想切换到CouchDB或elasticsearch,则不必更改对这些接口的调用,只需创建一个新的实现


因为,正如前面所述,您一般都很好,MongoDB的大多数函数都是
虚拟的
,这对大多数模拟库都很友好


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

请参见类似问题:


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

您需要一个存储库/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);
}
公共接口IDataContext
{
//质疑
IList GetAll();
IList GetByCriteria(查询);
T GetByID(字符串id);
//反刍
无效添加(T项);
作废删除(T项);
作废保存(T项);
}
  • 对于生产代码,在C#driver的帮助下实现与mongo db操作的接口
  • 对于单元测试代码,使用内存集合模拟接口
模拟添加/删除/保存看起来很简单,有趣的部分是查询函数。幸运的是,由于MongoC#driver支持LINQ表达式,我们可以使用LINQ作为查询语言,而不是重新发明轮子

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

// collection is a MongoCollection<T> object
var items = collection.AsQueryable().Where(...linq expression...);
//集合是MongoCollection对象
var items=collection.AsQueryable(),其中(…linq表达式…);
和单元测试代码(如果使用Shim,MS测试):

使用(ShimsContext.Create())
{                  
ShimlinkExtensionMethods.asQueryOfMongoCollectionOf0(
(MongoCollection x)=>Fake_DB_Collection.AsQueryable());
//在此之后,上面的“collection.AsQueryable()”将被模拟为
//内存中的集合,可以是IEnumerable的任何子类
} 

虽然我同意casperOne的观点,但是可以用大多数模拟框架模拟MongoDB驱动程序的类,因为公共方法是虚拟的。我将使用存储库模式。所以我需要嘲笑所有人,拯救,和其他人。这就是为什么我需要嘲笑mongo@kfuglsang更新了答案,具有不直接模拟MongoDB的优点。@F0rc0sigan您是在测试存储库的实现,还是在调用存储库?@F0rc0sigan抱歉,堆栈溢出不是代码编写服务。您还没有指出要模拟的方法、尝试过的方法或正在使用的模拟库。没有足够的信息,甚至无法开始尝试提供示例。GetByCriteria应返回IQueryable或IEnumerable
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>             
}