Frozen Mock is not the one that is being injected - Moq

Viewed 103

I'm trying to mock the UserService class. The problem is that if I use fixture.Register<UserManager<User>>(...) then it registers only the UserManager<User>, and this registration does not apply on Mock<UserManager<User>>.

The biggest problem is that the mock with [Frozen] attribute is not the one that is being injected into sut's contructor. Example:

UserManager customization

public class UserManagerCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Register(() =>
        {
            var mgr = new Mock<UserManager<User>>(Mock.Of<IUserRoleStore<User>>(),
                null, null, null, null, null, null, null, null);

            mgr.Setup(x => x.DeleteAsync(It.IsAny<User>()))
                    .ReturnsAsync(IdentityResult.Success);

            mgr.Setup(x => x.CreateAsync(It.IsAny<User>(), It.IsAny<string>()))
                .ReturnsAsync(IdentityResult.Success);

            mgr.Setup(x => x.UpdateAsync(It.IsAny<User>()))
                .ReturnsAsync(IdentityResult.Success);

            mgr.Setup(x => x.AddToRoleAsync(It.IsAny<User>(), It.IsAny<string>()))
                .ReturnsAsync(IdentityResult.Success);

            return mgr.Object;
        });
    }
}

AutoMoqData Attribute

public class AutoMoqDataAttribute : AutoDataAttribute
{
    public static IFixture FixtureFactory()
    {
        var f = new Fixture();

        f.Customize(new AutoMoqCustomization() { ConfigureMembers = true });
        f.Customize(new UserManagerCustomization());

        return f;
    }

    public AutoMoqDataAttribute() : base(FixtureFactory) { }
}

System under test

public class IdentityService : IIdentityService
{
    private readonly UserManager<User> _userManager;
    private readonly IMapper _mapper;
    private readonly IInfrastructureDbContext _dbContext;

    public IdentityService(
        UserManager<User> userManager,
        IMapper mapper,
        IInfrastructureDbContext dbContext)
    {
        _userManager = userManager;
        _mapper = mapper;
        _dbContext = dbContext;
    }

    public async Task<string> CreateUserAsync(UserViewModelIn user)
    {
        Guard.Against.Null(user, nameof(user));

        User newUser = _mapper.Map<User>(user);
        newUser.ProfileImage = new ProfileImage();

        var result = await _userManager.CreateAsync(newUser, user.Password);

        if (result.Succeeded)
        {
            await _userManager.AddToRoleAsync(newUser, "User");
        }

        return result.Succeeded ? newUser.Id : null;
    }
}

The test

[Theory]
[AutoMoqData]
public async Task CreateUser_ValidUser_ShouldCreateValidUserRecord(
    [Frozen] Mock<UserManager<User>> userManagerMock,
    IdentityService sut, // IdentityService injects UserManager<User>
    UserViewModelIn userVm)
{
    // Act
    await sut.CreateUserAsync(userVm);

    // Assert
    userManagerMock.Verify(m => m
        .CreateAsync(
            It.IsAny<User>(),
            It.IsAny<string>()
        ),
        Times.Once);
}

userManagerMock is not the same mock that gets passed to IdentityService's constructor, so this test always fails because the mock that I'm verified is not the one that IdentityService is callin upon user creation.

I want the fixture.Register<Service> to also cover the fixture.Register<Mock<Service>>, I don't know why this is not the default behavior.

0 Answers
Related