MongoDB is a widely used database and we usually come across situations where we have to unit test functions in DAL by mocking MongoDB SDK methods. It is little tricky when you want to mock the cursors and write the unit test cases.
Below are few samples on how to Mock MongoDB SDK and write unit tests in C# and XUnit and Moq.
Class to be Unit tested
Consider the below class to be unit tested which is a DAL layer. IMongoClient(which is a singleton defined in startup of .net core) is injected into the constructor. Database and collection instances are initiated in the constructor from IMongoClient.
GetProducts is a method that retrieves the list of products matching the input criteria using aggregation pipeline(utilizing MongoDB Atlas search). Ignore the complex pipeline here. I used it to show why Unit testing DAL methods are very important.
public class MongoDBService {
private readonly IMongoCollection < Products > productCollection;
public MongoDBService(IMongoClient mongoClient) {
var mongoDB = mongoClient.GetDatabase("databaseName");
this.productCollection = mongoDB.GetCollection < Products > ("collectionName");
}
public async Task < List < Products >> GetProducts(SearchRequestDTO searchRequestDTO) {
//Aggregation pipeline stages construction starts.
var departmentfilter = new BsonDocument {
{
MongoDBConstants.QueryOperator, searchRequestDTO.Department
}, {
MongoDBConstants.PathOperator,
ProductInfoConstants.Department
}
};
var categories = new BsonArray();
categories.AddRange(searchRequestDTO.Categories);
var categoryFilter = new BsonDocument {
{
MongoDBConstants.QueryOperator, categories
}, {
MongoDBConstants.PathOperator,
ProductInfoConstants.Categories
}
};
var must = new BsonArray();
must.Add(new BsonDocument {
{
MongoDBConstants.PhraseOperator, departmentfilter
}
});
must.Add(new BsonDocument {
{
MongoDBConstants.PhraseOperator, categoryFilter
}
});
foreach(var attribute in searchRequestDTO.AttributeFilter) {
string path = string.Empty;
ProductInfoConstants.Attributes.TryGetValue(attribute.K, out path);
var attributefilter = new BsonDocument {
{
MongoDBConstants.QueryOperator, attribute.V
}, {
MongoDBConstants.PathOperator,
path
}
};
must.Add(new BsonDocument {
{
MongoDBConstants.PhraseOperator, attributefilter
}
});
}
var compound = new BsonDocument {
{
MongoDBConstants.MustOperator, must
}
};
var search = new BsonDocument {
{
MongoDBConstants.IndexKey, MongoDBConstants.DefaultIndexvalue
}, {
MongoDBConstants.CompoundOperator,
compound
}
};
var searchStage = new BsonDocument {
{
MongoDBConstants.SearchOperator, search
}
};
var pipeline = new [] {
searchStage
};
//aggregation pipeline stages construction ends.
var result = await this.productCollection.AggregateAsync < Products > (pipeline);
return await result.ToListAsync();
}
}
In the above method, below line of code makes a database call to MongoDB that needs to be mocked.
await this.productCollection.AggregateAsync<Products>(pipeline)
Unit Test Step
To achieve the same and write unit test for GetProcuts Method using C3, XUnit, Moq, let's follow the steps below.
Step 1
Jithin MPosted Mar 2, 2023, 7:59 AM
How to Mock x.AggregateAsync().Project()