Unit Testing and Mock MongoDB DbContext in ASP.NET Core – Part1

Unit Test and Mock DBContext MongoDB in ASPNET Core

In our last article, we already learned the Implementation of a Repository pattern around the MongoDB database.

Today we will write Unit Test and Mock DBContext MongoDB in ASP.NET Core.

As we know, Unit Test cases can be written effectively if our implementation is programmed by abstraction i.e Interface.

Interface is the best friend of Unit testing

Today in this article we will cover below scenarios,

Here is an example of Context actual code,

public class MongoBookDBContext : IMongoBookDBContext
    {
        private IMongoDatabase _db { get; set; }
        private MongoClient _mongoClient { get; set; }
        public IClientSessionHandle Session { get; set; }

        public MongoBookDBContext(IOptions<Mongosettings> configuration)
        {
            _mongoClient = new MongoClient(configuration.Value.Connection);

            _db = _mongoClient.GetDatabase(configuration.Value.DatabaseName);
        }
      
        public IMongoCollection<T> GetCollection<T>(string name)
        {
            if(string.IsNullOrEmpty(name))
            {
                return null;
            }
            return _db.GetCollection<T>(name);
        }
    }

Let’s now look at writing unit test cases for the above class.

Please note that usually, the Context class can be created for each database that will hold multiple collections if required.

We shall create a mock for MongoDB Driver interfaces like IMongoDatabase, IMongoClient as below,

        private Mock<IOptions<Mongosettings>> _mockOptions;

        private Mock<IMongoDatabase> _mockDB;

        private Mock<IMongoClient> _mockClient;

We shall define a Test initialize method which will be Constructor while using XUnit.

Please note that in XUnit constructor will be invoked before each test method.

 public MongoBookDBContextTests()
        {
            _mockOptions = new Mock<IOptions<Mongosettings>>();
            _mockDB = new Mock<IMongoDatabase>();
            _mockClient = new Mock<IMongoClient>();
        }

Unit Test 1 – Unit Test and Mock DBContext MongoDB

Here we would be writing unit test cases if Constructor is invoked.

If the constructor is invoked successfully, the object will be created successfully.

        [Fact]
        public void MongoBookDBContext_Constructor_Success()
        {
            var settings = new Mongosettings()
            {
                Connection = "mongodb://tes123 ",
                DatabaseName = "TestDB"
            };

            _mockOptions.Setup(s => s.Value).Returns(settings);
            _mockClient.Setup(c => c
            .GetDatabase(_mockOptions.Object.Value.DatabaseName, null))
                .Returns(_mockDB.Object);

            //Act 
            var context = new MongoBookDBContext(_mockOptions.Object);

            //Assert 
            Assert.NotNull(context);
        }

Unit Test 2- Unit Test and Mock GetCollection MongoDB

We shall now write Unit test cases for the GetCollection method,

 
 public IMongoCollection<T> GetCollection<T>(string name)
        {

            return _db.GetCollection<T>(name);
        }

Let’s write a test for the -ve scenario i.e when the collection name is passed as empty.

  [Fact]
public void MongoBookDBContext_GetCollection_NameEmpty_Failure()
        {

            //Arrange
            var settings = new Mongosettings()
            {
                Connection = "mongodb://tes123",
                DatabaseName = "TestDB"
            };

            _mockOptions.Setup(s => s.Value).Returns(settings);
            _mockClient.Setup(c => c
            .GetDatabase(_mockOptions.Object.Value.DatabaseName, null))
                .Returns(_mockDB.Object);

            //Act 
            var context = new MongoBookDBContext(_mockOptions.Object);
            var myCollection = context.GetCollection<Book>("");

            //Assert 
            Assert.Null(myCollection);

        }

Similarly, Let’s write a test for the +ve scenario i.e when a valid collection name is passed.

Unit Test 3 – Unit test and Mock IMongoClient, IMongoCollection interface.

Here we will verify if the GetCollection method returns a proper collection.

        [Fact]
        public void MongoBookDBContext_GetCollection_ValidName_Success()
        {
            //Arrange
            var settings = new Mongosettings()
            {
                Connection = "mongodb://tes123 ",
                DatabaseName = "TestDB"
            };

            _mockOptions.Setup(s => s.Value).Returns(settings);

            _mockClient.Setup(c => c.GetDatabase(_mockOptions.Object.Value.DatabaseName, null)).Returns(_mockDB.Object);

            //Act 
            var context = new MongoBookDBContext(_mockOptions.Object);
            var myCollection = context.GetCollection<Book>("Book");

            //Assert 
            Assert.NotNull(myCollection);
        }

Unit Test for Async method?

Please see the below article for Async method examples,

  • Unit Testing and Mocking MongoDB DBContext Part 2
  • Do you think the above 3-4 unit test cases should be enough for making DBContext class robust enough? You may want to add some more test cases.

    Further, you can mock IAsyncCursor and their extension methods too.

    Other references :

    Please sound off your comments below.



    Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.



    One thought on “Unit Test and Mock DBContext MongoDB in ASP.NET Core

    Leave a Reply

    Your email address will not be published. Required fields are marked *