MongoDB C#驱动程序Mock方法返回IAsyncCursor

时间:2018-01-09 20:18:14

标签: c# mongodb unit-testing moq mongodb-.net-driver

我为使用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>为空时,测试无效。

模拟此方法并处理IAsyncCursor的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

模拟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.

有关如何枚举光标的参考,请查看此答案。

How is an IAsyncCursor used for iteration with the mongodb c# driver?

在此之后,您将能够理解为什么模拟设置了移动下一个方法的序列。

答案 1 :(得分:0)

如果它对其他人有帮助......我从@Nkosi的嘲笑答案中实现了一个c#类

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 async Task<bool> MoveNextAsync(CancellationToken cancellationToken)
    {
        return !called && (called = true);
    }

    public void Dispose()
    {
    }
}