Search code examples
c#entity-frameworkmoqdbset

How to mock dbSet.AddAsync(obj).Entity


I have a project with unit and integration test. Unfortunately, I cannot use any integration test for some reasons so I am obliged to use unit tests.

I have have the code bellow in my project.

var associationEntity = (await _context.UsersAssociations.AddAsync(association)).Entity;
await _context.Entry(associationEntity.Guest).Collection(g => g.Accounts).LoadAsync();

_context is an Entity Framework DbContext. I am using AddAsync for better performances so I cannot use .Add(association) method.

I am using mocks with Moq and I am mocking the DbContext.

My objective is to get the .Entity object for my unit tests. Unfortunately, all my tries and what the internet offers couldn't make it work. await _context.UsersAssociations.AddAsync(association) is always returning null and not an EntityEntry as it should.

Here is my latest try:

var dbContextMock = UnitTestHelper.GetDbContextMock();
var usersAssociationsSetMock = UnitTestHelper.GetDbSetMock(new List<UsersAssociation>());

var usersAssociationEntryMock = new Mock<EntityEntry<UsersAssociation>>();
usersAssociationEntryMock.Setup(x => x.Entity)
    .Returns(userAssociationMock); // It should returns an object defined before this part.

usersAssociationsSetMock.Setup(x => x.AddAsync(It.IsAny<UsersAssociation>(), It.IsAny<CancellationToken>()))
    .Returns((UsersAssociation model, CancellationToken token) => new ValueTask<EntityEntry<UsersAssociation>>(usersAssociationEntryMock.Object));

I was thinking that the entryMock.Entity could give me the usersAssociationMock. However, usersAssociationEntryMock.Object is not working. An error appears: "Could not find a parameterless constructor".

And here's what I've tried and why it didn't succeed:

If by any chance you have an idea, or need more code, don't hesitate :) I found very little help on the dbSet.AddAsync() mocking so even less help on what I want.

Thank you by advance and have a nice day even if you didn't help me :D


Solution

  • The answer is that we cannot do it. We can't mock an EntityEntry object and it should not be done. Here's the source: https://github.com/dotnet/ef6/issues/208

    Instead an in-memory database should be used for unit testing with database transactions.

    (Didn't try it yet)