Unit Testing and Mock MongoDB DbContext in ASP.NET Core – Part1
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,
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.
Hi – Thanks for your comments. I agree with you. I did use IAsyncursor to mock and iterate the entities to overcome the challenge. Please do visit this postUnit Testing and Mocking MongoDB Extension Methods in .NET Core – Part2