I am getting the following exception when trying to unit test a db call to a mongo database that uses ProjectionDefinition: "Value cannot be null.\r\nParameter name: projection". This is caused because during assignment for the MongoDb C# driver ProjectionDefinition class, there is a null check that throws this exception. Here is the call stack for the exception:
{System.ArgumentNullException: Value cannot be null.
Parameter name: projection
at MongoDB.Driver.Core.Misc.Ensure.IsNotNull[T](T value, String paramName)
at MongoDB.Driver.KnownResultTypeProjectionDefinitionAdapter`2..ctor(ProjectionDefinition`1 projection, IBsonSerializer`1 projectionSerializer)
at MongoDB.Driver.ProjectionDefinition`2.op_Implicit(ProjectionDefinition`1 projection)
at DataCollection.Data.Mongo.Test.Collection.ComponentRecordCollectionTest.LogsExceptionWhenOnGetRecordUserViews() in C:\Repositories\Folio\folio-data-collection-api\src\DataCollection.Data.Mongo.Test\Collection\ComponentRecordCollectionTest.cs:line 447}
I am using the NSubstitute Arg.Is to test the value of the projection within my function.
var expectedProjection = Arg.Is<ProjectionDefinition<ComponentRecordDataModel>>(
x => x.ToJson().Equals(projection.ToJson()));
I've noticed that this causes expectedProjection to be null which triggers the exception. I'm not sure how this works but I am doing the exact same thing with testing FilterDefinition and it works with no issues. I've even tested with the examples from the NSubstitue documentation an even though the Arg.Is returns null the argument matchers work.
Here is the function that I am trying to test:
public ComponentRecordDataModel GetRecordUserViews(string id)
{
var filter = Builders<ComponentRecordDataModel>.Filter.Eq(x => x.Id, id);
var projection = Builders<ComponentRecordDataModel>.Projection.Include(x => x.UserViews);
var result = MongoContext.Find(filter, projection).FirstOrDefault();
return result;
}
and here is the test:
[Fact]
public void LogsExceptionWhenOnGetRecordUserViews()
{
var filter = Builders<ComponentRecordDataModel>.Filter.Eq(x => x.Id, _recordModel.Id);
var projection = Builders<ComponentRecordDataModel>.Projection.Include(x => x.UserViews);
var expectedFilter = Arg.Is<FilterDefinition<ComponentRecordDataModel>>(
x => x.ToJson().Equals(filter.ToJson()));
var expectedProjection = Arg.Is<ProjectionDefinition<ComponentRecordDataModel>>(
x => x.ToJson().Equals(projection.ToJson()));
_mongoContext.Find(expectedFilter, expectedProjection).Throws(_exception);
Assert.Throws(typeof(DataAccessException), () => _collection.GetRecordUserViews(_recordModel.Id));
_logger.CheckReceivedLog(LogLevel.Error, LoggingEvents.GeneralException, _exception.Message);
}
I'm wondering if there is something I am doing wrong here or if someone has an alternative approach to getting this code tested. Thanks in advance!