Search code examples
c#entity-frameworkunit-testingmoqautofac

UnitTesing with Autofac, Moq - Getting Value cannot be null exception


I'm using EF6. The generated code is something like:

public partial class MyDataContext : DbContext,IMyDataContext 
{
    public MyDataContext() : base("name=mydata")
    {
    }

    public virtual DbSet<getProjectsDraft> getProjectsDrafts { get; set; }
}

and the dbcontext Interface is like below

public interface IxmcmcDbContext: IDisposable
{
   DbSet<getProjectsDraft> getProjectsDrafts { get; set; }
}

I am using the Autofac for the DI and the registration is done at my global.asax.cs as below

//Entity Registering
builder.RegisterType<MyDataContext>().As<IMyDataContext>();

All my DI is working fine but when I implemented unit testing using xUnity I am getting below error

Basetest Code:

public class BaseTest
    {
        public static Mock<DbSet<T>> CreateDbSetMock<T>(IEnumerable<T> elements) where T : class
        {
            var elementsAsQueryable = elements.AsQueryable();
            var dbSetMock = new Mock<DbSet<T>>();
            dbSetMock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(elementsAsQueryable.Provider);
            dbSetMock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(elementsAsQueryable.Expression);
            dbSetMock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(elementsAsQueryable.ElementType);
            dbSetMock.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(elementsAsQueryable.GetEnumerator());
            return dbSetMock;
        }
    }

and Project Test

public class Projects_Test : BaseTest
    {
        [Fact]
        public void GetDraftProjectsList()
        {
            // Arrange
            var fixture = new Fixture();
            var draftProjects = new List<getProjectsDraft>
             {
                fixture.Create<getProjectsDraft>()
             };
            var draftMock = CreateDbSetMock(draftProjects);
            var myDataContextMock= new Mock<IMyDataContext>();
            myDataContextMock.Setup(x => x.getProjectsDrafts).Returns(draftMock.Object);
            var projectService = new ProjectRepo(mediciContextMock.Object);

            // Act
            var draftproject = projectService.GetDraftProjects(true, "test-02", "Test");

            // Assert
            Assert.NotNull(draftproject);
        }
    }

However, I get the "Value cannot be null.\r\nParameter name: source" error on the //Act draftproject.

What am I doing wrong?


Solution

  • You are almost there, the DbSet is mocked properly but looking at the method, you will notice the AsNoTracking method which is actually not mocked and it returns null.

    lstDraftProj = (from proj in mydbEntities.getProjectsDrafts.AsNoTracking()
                    orderby proj.ProjectID descending
                    select proj).ToList();
    

    That is also suggested by stack trace:

    System.ArgumentNullException HResult=0x80004003 Message=Value cannot be null. Parameter name: source

    Since you are already mocking DbSet try mocking the AsNoTracking method as well, e.g:

    draftMock.Setup(x => x.AsNoTracking()).Returns(draftMock.Object)