我如何对MongoDB查询过滤器进行单元测试?



我有一个类似于以下的场景(为了清晰起见简化了):

public class ExampleRepository
{
private readonly IMongoDatabase _db;
public ExampleRepository(IMongoClient mongoClient)
{
this._db = mongoClient.GetDatabase("database");
}
public async Task<IEnumerable<Item>> GetItemsUsingFilter(Guid ownerId, DateTimeOffset createdSince, IEnumerable<ItemType> typesToIgnore)
{
var cursor = await this._db.GetCollection<Item>("Items")
.FindAsync(item =>
item.OwnerId == ownerId
&&
item.CreatedDate >= createdSince
&&
!typesToIgnore.Contains(item.Type)
.SortByDescending(item => item.UserRating)
.Limit(10);
return await cursor.ToListAsync();
}
}

我想编写单元测试来验证我的查询过滤器的正确性(以及排序和限制调用),但是我不知道如何设置测试数据来这样做。

我尝试模拟IMongoDatabase并设置GetCollection调用以返回模拟IMongoCollection,但这不是正确的方法,因为我需要在真正的monongocollection上调用FindAsync调用。

我考虑通过拆分GetCollection调用来改变存储库,然后使用标准LINQ应用过滤,但我不想从DB返回我的整个集合,然后在存储库层中查询它。

我发现了几个人对MongoDB进行单元测试的例子,但这些都涉及模拟FindAsync调用,这不是我需要做的。

我还考虑将过滤器声明为Expression<Item,>>在一个单独的类中,所以我可以单独测试它,但我想在走这条路之前探索其他选项,因为它增加了存储库层的复杂性。

我没有使用MongoDB,但从纯单元测试的角度来看,这是我的方法:

  • 观察测试中的方法有四个输入:IMongoClient依赖项(我认为是间接输入)和三个参数(直接输入)。
  • 创建一个对象实现IMongoDatabase (MD)和模拟IMongoClient返回它。创建一个实现IMongoCollection (MC)的对象,并由MD的GetCollection方法返回;MC实际上是你的测试数据。
  • 定义三个参数传递给被测试的方法。

现在可以执行测试了。

请注意,MC的实现包括FindAsync等方法,但这没关系,因为您的目的不是测试MongoDB的功能,而是测试您的方法的流程和行为。

看一下这个过于简化的例子(基于你的代码):

public async Task<IEnumerable<string>> GetItemsUsingFilter()
{
var cursor = await this._db.GetCollection<string>("Items")
.SortByDescending()
.Limit(10);
return await cursor.ToListAsync();
}

如果GetCollection在生产环境中返回12项,&;a &;…&;l &;,我们希望&;l &;…&;待归还。此外,我们希望我们的测试失败,例如,如果其他一些开发人员错误地将Limit移动到sortbydescent之前(这将导致产品代码返回& & &;…& &;a & &;)。

相关内容

  • 没有找到相关文章

最新更新