C# – How to Mock IMongoCollection.Find using Moq

.net corecmongodbmoqunit testing

I am struggling in mocking IMongoCollection.Find method using Moq for my unit tests.

What I tried:

  Mock<IMongoCollection<Person>> mockIMongoCollection = new Mock<IMongoCollection<Person>>();
  mockIMongoCollection.SetupAllProperties();
  mockIMongoCollection
            .Setup(x => x.Find(
                It.IsAny<FilterDefinition<Person>>(),
                It.IsAny<FindOptions>()))
            .Returns();

The thing is whatever I try to return using Returns(), it is not working, I expect to be able to return something convertible to List<Person> and I can't mock or create an instance of IFindFluent<Person,Person> as suggested by return type of Find method.

Best Answer

Maby this will help you.

I had to Mock such query:

 var queryRecords = await queryCollection
                .Find(filters)
                .Project(projection)
                .Skip(queryCriteria.Skip)
                .Limit(queryCriteria.Limit)
                .Sort(sort);

to do that I created an abstraction for MongoCollection to handle mongo queries.

public interface IFakeMongoCollection : IMongoCollection<BsonDocument>
{
    IFindFluent<BsonDocument, BsonDocument> Find(FilterDefinition<BsonDocument> filter, FindOptions options);

    IFindFluent<BsonDocument, BsonDocument> Project(ProjectionDefinition<BsonDocument, BsonDocument> projection);

    IFindFluent<BsonDocument, BsonDocument> Skip(int skip);

    IFindFluent<BsonDocument, BsonDocument> Limit(int limit);

    IFindFluent<BsonDocument, BsonDocument> Sort(SortDefinition<BsonDocument> sort);
}

So my tests setup looks like this

[TestFixture]
class QueryControllerTests
{
    private IOptions<MongoSettings> _mongoSettings;
    private QueryController _queryController;
    private Mock<IFakeMongoCollection > _fakeMongoCollection;
    private Mock<IMongoDatabase> _fakeMongoDatabase;
    private Mock<IMongoContext> _fakeMongoContext;
    private Mock<IFindFluent<BsonDocument, BsonDocument>> _fakeCollectionResult;

    [OneTimeSetUp]
    public void Setup()
    {
        _fakeMongoCollection = new Mock<IFakeMongoCollection >();
        _fakeCollectionResult = new Mock<IFindFluent<BsonDocument, BsonDocument>>(
        _fakeMongoDatabase = new Mock<IMongoDatabase>();
        _fakeMongoDatabase
            .Setup(_ => _.GetCollection<BsonDocument>("Test", It.IsAny<MongoCollectionSettings>()))
            .Returns(_fakeMongoCollection.Object);

        _fakeMongoContext = new Mock<IMongoContext>();
        _fakeMongoContext.Setup(_ => _.GetConnection()).Returns(_fakeMongoDatabase.Object);        
        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", false)
            .Build();
        _mongoSettings = Options.Create(configuration.GetSection("MongoConnection").Get<MongoSettings>());
        _queryController = new QueryController(_mongoSettings, _fakeMongoContext.Object);
    }
}

I hope it helps.