我正在对 MongoDB C# 驱动程序的包装器进行单元测试。我有这行代码:
Collection.Find(predicate).ToListAsync();
其中
Collection
是 IMongoCollection<T>
类型,并且 Find(predicate)
返回实现 IFindFluent<T, T>
的实例。我认为 ToListAsync()
是将结果转换为列表的扩展。
我正在尝试编写单元测试,但我很难处理这个问题。我无法制作包装类,因为这就是我正在做的事情。我更愿意让
ToListAsync()
返回一个创建的列表,或者模拟 Find()
以返回可以制作列表的内容。
如果有人很难让它工作,我对
Find()
方法所做的模拟是:
[TestFixture]
class QueryControllerTests
{
private IOptions<MongoSettings> _mongoSettings;
private QueryController _queryController;
private Mock<IFakeMongoCollection> _fakeMongoCollection;
private Mock<IFindFluent<BsonDocument, BsonDocument>> _fakeCollectionResult;
[OneTimeSetUp]
public void Setup()
{
_fakeMongoCollection = new Mock<IFakeMongoCollection>();
_fakeCollectionResult = new Mock<IFindFluent<BsonDocument, BsonDocument>>();
}
}
其中
IFakeMongoCollection
是:
public interface IFakeMongoCollection : IMongoCollection<BsonDocument>
{
IFindFluent<BsonDocument, BsonDocument> Find(FilterDefinition<BsonDocument> filter, FindOptions options);
}
我最终为此做了一个小抽象层,因为我找不到任何合适的东西并且寻求帮助也没有得到答案。
我创建了一个名为
AppCollection
的接口/实现对,专门用于处理 MongoDB 接口。 IAppCollection
将有一个 IAppCollection.ToList(predicate)
的方法,并且 AppCollection
将运行 Collection.Find(predicate).ToListAsync();
调用,返回列表。后来,嘲笑 IAppCollection
以确保做出正确的调用就变得微不足道了。虽然我无法在本机 LINQ 中测试谓词,但我至少可以编译谓词并将它们与通过/失败的对象进行比较。
var returnList = new List<DbRecord>();
//add your records to the list
// Mocking the IAsyncCursor that ToListAsync would internally use
var mockCursor = new Mock<IAsyncCursor<DbRecord>>();
mockCursor.SetupSequence(x => x.MoveNextAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(true)
.ReturnsAsync(false);
mockCursor.Setup(x => x.Current)
.Returns(returnList);
现在您可以从您的
Mock<IMongoCollection<T>>
归还它
mockMongoCollection.Setup(m => m.FindAsync(It.IsAny<FilterDefinition<DbRecord>>(),
It.IsAny<FindOptions<DbRecord>>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(mockCursor.Object);