sam0606
sam0606

Reputation: 31

Mocking MongoDb Methods such as Find,FindAsync Method in Xunit

I am trying to mock mongodb's findasync,find methods in Xunit & .net core.

When i tried to mock the InsertOne,

mockcollection.setup(x=>x.InsertOneAsync(_newitem,null,It.IsAny<CancellationToken>()).Returns(task.CompletedTask);

but the find is throwing error "Extension Method FindAsync may not be used in setup/verify process.

mockcollection.setup(x=>x.FindAsync(It.IsAny<FilterDefinition<mytbl>>(),null,It.IsAny<CancellationToken>()).Returns(Task.FromResult(mockasyncursor.Object));

When i surfed all over the net all it says is extension methods cannot be mocked, the above method [FindAsync] is a an extension method where as InsertOne is not.

How can i mock the findasync method?

Note: I tried using Mongo2go to simulate the db and able to come up with positive results, but wanted to know how to do using mock ?

Method:

public async Task<IEnumerable<XX>> abc()
{
_logger.LogInformation("XXX");

var result = _context
        .XX.FindAsync(_ => true, null, CancellationToken.None);

return ( await _context.XX.FindAsync(_ => true) ).ToList<XX>();
}

Unit Test Method:

public async Task XXX()
{
    // Arrange
    var XX = this.XX();
                < IAsyncCursor < XX >> mockasynccursor = new Mock<IAsyncCursor<XX>>();
    mockXXCollection = new Mock<IMongoCollection<XX>>();

    mockasynccursor.Setup(_ => _.Current).Returns(ReadfromJson());
    mockasynccursor.
        SetupSequence
        (_ => _.MoveNext(It.IsAny<CancellationToken>())).Returns(true).Returns(false);


    //sample
    var newitem = new XX { };
    mockXXCollection.
        Setup(x => x.InsertOneAsync(newitem, null, default(CancellationToken)))
        .Returns(Task.CompletedTask);

    //Error Here 
    mockXXCollection.Setup(x => x.FindAsync(It.IsAny<FilterDefinition<XX>>(), null, CancellationToken.None))
        .Returns(Task.FromResult(mockasynccursor.Object));

    //Message: System.NotSupportedException : Unsupported expression: x => x.FindAsync<XX>(It.IsAny<FilterDefinition<XX>>(), null, CancellationToken.None)
    //Extension methods( here: IMongoCollectionExtensions.FindAsync) may not be used in setup / verification expressions.



    mockStateFormContext.Setup(x => x.StateForms).Returns(mockXXCollection.Object);

    // Act
    var result = await xyzRepository.abc();

    // Assert

}

Upvotes: 2

Views: 6100

Answers (1)

Nkosi
Nkosi

Reputation: 247333

The instance FindAsync definition looks like this

Task<IAsyncCursor<TProjection>> FindAsync<TProjection>(
    FilterDefinition<TDocument> filter,
    FindOptions<TDocument, TProjection> options = null,
    CancellationToken cancellationToken = null
)

All the extension methods will eventually call back to this member.

When configuring the mock make sure that the instance member is explicitly being setup

//...

mockXXCollection
    .Setup(_ => _.FindAsync(
        It.IsAny<FilterDefinition<XX>>(), 
        It.IsAny<FindOptions<XX, XX>>(), 
        It.IsAny<CancellationToken>()
    ))
    .ReturnsAsync(mockasynccursor.Object);

//...

Upvotes: 7

Related Questions