3

I am unit testing a get call using Moq. I am using Automapper to pull data from a SQL database and map it into my view models. My method looks something like this:

public virtual IEnumerable<ViewParentTable> Get()
{
    Mapper.CreateMap<ParentTable, ViewParentTable>();
    Mapper.CreateMap<ChildTable, ViewChildTable>()

    IEnumerable<ViewParentTable> tableresult = db.ParentTable
         .Include("ChildTable")
         .Project().To<ViewParentTable>();

    return tableresult;
}

And my test looks something like this:

[TestMethod]
public void Get()
{
    IEnumerable<ViewParentTable> returned = method.Get();
    mockContext.VerifyGet(m => m.ParentTable);
}

I have mocked the DbContext as such:

this.mockParentSet = new Mock<DbSet<ParentTable>>();
this.mockChildSet = new Mock<DbSet<ChildTable>>();

mockParentSet.As<IQueryable<ParentTable>>().Setup(m => m.Provider).Returns(mockParentData.Provider);
mockParentSet.As<IQueryable<ParentTable>>().Setup(m => m.Expression).Returns(mockParentData.Expression);
mockParentSet.As<IQueryable<ParentTable>>().Setup(m => m.ElementType).Returns(mockParentData.ElementType);
mockParentSet.As<IQueryable<ParentTable>>().Setup(m => m.GetEnumerator()).Returns(mockParentData.GetEnumerator());

mockChildSet.As<IQueryable<ChildTable>>().Setup(m => m.Provider).Returns(mockChildData.Provider);
mockChildSet.As<IQueryable<ChildTable>>().Setup(m => m.Expression).Returns(mockChildData.Expression);
mockChildSet.As<IQueryable<ChildTable>>().Setup(m => m.ElementType).Returns(mockChildData.ElementType);
mockChildSet.As<IQueryable<ChildTable>>().Setup(m => m.GetEnumerator()).Returns(mockChildData.GetEnumerator());

this.mockContext = new Mock<MyContext>();
this.mockContext.Setup(m => m.ParentTable).Returns(mockParentSet.Object);
this.mockContext.Setup(m => m.ChildTable).Returns(mockChildSet.Object);

I have filled both ParentTable and ChildTable with data. If I remove the Include("ChildTable"), the test passes. However, with the Include("ChildTable") in place an exception is thrown on the db call, Value cannot be null. All non-nullable fields in both Child and Parent tables are populated, so I'm not sure what is causing the error.

yammerade
  • 629
  • 8
  • 20
  • I don't know how Moq deals with mocking `DbSet`, but with other mocking frameworks I've used you have to realize they are not actually a database, so they are not going to do the joins necessary to include the related data. instead, you have to load them with the fully-formed object graph so they can spit it back out as if a real database had joined the data. – Craig W. Jun 17 '16 at 15:47
  • Yes, I am handling that. When I construct the test data, I loop through each element of `ParentTable` and assign `item.ChildItems` based on ids. Similarly, I loop through each element of `ChildTable` and assign `item.ParentItem` based on id. – yammerade Jun 17 '16 at 15:51
  • I don't think this test adds any value. Aren't you just testing AutoMapper at this point? – Spivonious Jun 17 '16 at 16:15
  • This is a simplified version of what I'm doing. The point is it never gets to the `VerifyGet` because it throws an exception executing the method. – yammerade Jun 17 '16 at 16:25
  • I have the same problem. Did you manage to make it work? – Alexandre Pepin Feb 24 '21 at 20:48

1 Answers1

0

I manage to get it work by following this answer

mockParentSet.Setup(m => m.Include(It.IsAny<string>())).Returns(mockParentSet.Object);
Alexandre Pepin
  • 1,816
  • 3
  • 20
  • 36