MongoDB Mock and Unit Test a method returning IAsyncCursor

MongoDB Mock and Unit Test a method returning IAsyncCursor Synchronously

In this article, I shall talk about how to perform MongoDB Mock and Unit Test a method returning IAsyncCursor Synchronously

Today in this article, we will cover below aspects,

We shall use the below example and write a test method with mocking.

Below examples are already discussed in detail in our post-MongoDB Repository implementation in .NET Core with example

Example

Below is an example method for which we shall be writing mocking and unit test cases.

  
public IEnumerable<TEntity> GetAllSync()
        {
            var all =  _dbCollection.Find(Builders<TEntity>.Filter.Empty,null);
            return all.ToList();
        }

Let’s define the constructor for initial setup up (If using XUnit this constructor shall execute for every test case and set up initial test data required for each test case)

Constructor for the Test class

Please see here below article for constructor initialization,

IAsyncCursor and Mocking

Let’s now mock IAsyncursor. Overall there are two methods that IAsyncursor exposes.

The IAsyncCursor<TDocument> type exposes the following methods,

  • MoveNext()
  • MoveNextAsync()

For Asynchronous method mocking, please visit here – MongoDB Mock and Unit Test a method returning IAsyncCursor

We shall mock MoveNext() for synchronous operation,

           //Mock MoveNext
            Mock<IAsyncCursor<Book>> _bookCursor = new Mock<IAsyncCursor<Book>>();
            _bookCursor.Setup(_ => _.Current).Returns(_list);
            _bookCursor
                .SetupSequence(_ => _.MoveNext(It.IsAny<CancellationToken>()))
                .Returns(true)
                .Returns(false);

We shall set up current as a list of books as defined in the mock above.

Define Test Methods as below,

        [Fact]
        public  void BookRepository_GetBookSync_Valid_Success()
        {
            //Arrange
            //Mock FindSync
            _mockCollection.Setup(op => op.FindSync(It.IsAny<FilterDefinition<Book>>(),
            It.IsAny<FindOptions<Book, Book>>(),
             It.IsAny<CancellationToken>())).Returns(_bookCursor.Object);

            //Mock GetCollection
            _mockContext.Setup(c => c.GetCollection<Book>(typeof(Book).Name)).Returns(_mockCollection.Object);

            var bookRepo = new BookRepository(_mockContext.Object);

            //Act
            var result =  bookRepo.GetAllSync();

            //Assert 
            //loop only first item and assert all details
            foreach (Book book in result)
            {
                Assert.NotNull(book);
                Assert.Equal(book.Name, _book.Name);
                Assert.Equal(book.Author, _book.Author);
                break;
            }

            //Verify if FindSync is called once 
            _mockCollection.Verify(c => 
               c.FindSync(It.IsAny<FilterDefinition<Book>>(),
               It.IsAny<FindOptions<Book>>(),
               It.IsAny<CancellationToken>()), Times.Once);
        }

With the above code and mock setup, I can very much unit test actual result vs expected result easily.

Apart from that, I can very much Assert using Verify() to confirm if the extension method has been invoked once.

Other references :

Do you have any better suggestions to test the method with AsyncCursor?

Please sound off your comments below!

Happy Coding !!



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.



Leave a Reply

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