MongoDB returns IAsyncCursor 的 C# 驱动程序 Mock 方法
MongoDB C# driver Mock method that returns IAsyncCursor
我正在为使用 mongoDB c# 驱动程序的 DAL 创建一些单元测试。问题是我有这个方法要测试:
public async virtual Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> predicate)
{
return (await Collection.FindAsync(predicate)).ToList();
}
并使用 Moq 我已经像这样模拟了这个集合:
var mockMongoCollectionAdapter = new Mock<IMongoCollectionAdapter<Entity>>();
var expectedEntities = new List<Entity>
{
mockEntity1.Object,
mockEntity2.Object
};
mockMongoCollectionAdapter.Setup(x => x.FindAsync(It.IsAny<Expression<Func<Entity,bool>>>(), null, default(CancellationToken))).ReturnsAsync(expectedEntities as IAsyncCursor<Entity>);
但由于 expectedEntities as IAsyncCursor<Entity>
为 null,因此测试无效。
模拟此方法和处理 IAsyncCursor 的最佳方法是什么?
模拟 IAsyncCursor<TDocument> interface
以便它可以被枚举。反正接口上的方法不多
var mockCursor = new Mock<IAsyncCursor<Entity>>();
mockCursor.Setup(_ => _.Current).Returns(expectedEntities); //<-- Note the entities here
mockCursor
.SetupSequence(_ => _.MoveNext(It.IsAny<CancellationToken>()))
.Returns(true)
.Returns(false);
mockCursor
.SetupSequence(_ => _.MoveNextAsync(It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(true))
.Returns(Task.FromResult(false));
mockMongoCollectionAdapter
.Setup(x => x.FindAsync(
It.IsAny<Expression<Func<Entity, bool>>>(),
null,
It.IsAny<CancellationToken>()
))
.ReturnsAsync(mockCursor.Object); //<-- return the cursor here.
有关如何枚举游标的参考,请查看此答案。
在此之后,您将能够理解为什么要为 mock 设置 move next 方法的序列。
如果它对其他人有帮助....根据@Nkosi 的嘲讽回答,我实现了以下 class
public class MockAsyncCursor<T> : IAsyncCursor<T>
{
private readonly IEnumerable<T> _items;
private bool called = false;
public MockAsyncCursor(IEnumerable<T> items)
{
_items = items ?? Enumerable.Empty<T>();
}
public IEnumerable<T> Current => _items;
public bool MoveNext(CancellationToken cancellationToken = new CancellationToken())
{
return !called && (called = true);
}
public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
{
return Task.FromResult(MoveNext(cancellationToken));
}
public void Dispose()
{
}
}
我正在为使用 mongoDB c# 驱动程序的 DAL 创建一些单元测试。问题是我有这个方法要测试:
public async virtual Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> predicate)
{
return (await Collection.FindAsync(predicate)).ToList();
}
并使用 Moq 我已经像这样模拟了这个集合:
var mockMongoCollectionAdapter = new Mock<IMongoCollectionAdapter<Entity>>();
var expectedEntities = new List<Entity>
{
mockEntity1.Object,
mockEntity2.Object
};
mockMongoCollectionAdapter.Setup(x => x.FindAsync(It.IsAny<Expression<Func<Entity,bool>>>(), null, default(CancellationToken))).ReturnsAsync(expectedEntities as IAsyncCursor<Entity>);
但由于 expectedEntities as IAsyncCursor<Entity>
为 null,因此测试无效。
模拟此方法和处理 IAsyncCursor 的最佳方法是什么?
模拟 IAsyncCursor<TDocument> interface
以便它可以被枚举。反正接口上的方法不多
var mockCursor = new Mock<IAsyncCursor<Entity>>();
mockCursor.Setup(_ => _.Current).Returns(expectedEntities); //<-- Note the entities here
mockCursor
.SetupSequence(_ => _.MoveNext(It.IsAny<CancellationToken>()))
.Returns(true)
.Returns(false);
mockCursor
.SetupSequence(_ => _.MoveNextAsync(It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(true))
.Returns(Task.FromResult(false));
mockMongoCollectionAdapter
.Setup(x => x.FindAsync(
It.IsAny<Expression<Func<Entity, bool>>>(),
null,
It.IsAny<CancellationToken>()
))
.ReturnsAsync(mockCursor.Object); //<-- return the cursor here.
有关如何枚举游标的参考,请查看此答案。
在此之后,您将能够理解为什么要为 mock 设置 move next 方法的序列。
如果它对其他人有帮助....根据@Nkosi 的嘲讽回答,我实现了以下 class
public class MockAsyncCursor<T> : IAsyncCursor<T>
{
private readonly IEnumerable<T> _items;
private bool called = false;
public MockAsyncCursor(IEnumerable<T> items)
{
_items = items ?? Enumerable.Empty<T>();
}
public IEnumerable<T> Current => _items;
public bool MoveNext(CancellationToken cancellationToken = new CancellationToken())
{
return !called && (called = true);
}
public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
{
return Task.FromResult(MoveNext(cancellationToken));
}
public void Dispose()
{
}
}