Search code examples
c#unit-testingasp.net-corexunit

Mock user manager using unit test ASP.NET Core


I am working on an application where I need to mock a UserManager but getting a null response from CreateAsync. Below are my services and unit test code.

[Fact]
public async Task RegisterUser_Exceptions()
{
    // Initialize AutoMapper with the defined profile
    var configuration = new MapperConfiguration(cfg => cfg.AddProfile<UserMapperProfile>());
    var mapper = configuration.CreateMapper();

    // Mock the UserManager
    var userStoreMock = new Mock<IUserStore<AppUser>>();
    var userManagerMock = new Mock<UserManager<AppUser>>(
            userStoreMock.Object,
            new Mock<IOptions<IdentityOptions>>().Object,
            new Mock<IPasswordHasher<AppUser>>().Object,
            new IUserValidator<AppUser>[0],
            new IPasswordValidator<AppUser>[0],
            new Mock<ILookupNormalizer>().Object,
            new Mock<IdentityErrorDescriber>().Object,
            new Mock<IServiceProvider>().Object,
            new Mock<ILogger<UserManager<AppUser>>>().Object);

    // Setup CreateAsync to return a successful IdentityResult
    userManagerMock.Setup(x => x.CreateAsync(It.IsAny<AppUser>(), It.IsAny<string>()))
            .ReturnsAsync(IdentityResult.Success);

    // Instantiate the UserManagementService with the actual AutoMapper instance
    var userManagementService = new UserManagementService(userManagerMock.Object, mapper);

    // Create a UserRegisterationDto with all required properties
    var userRegistrationDto = new UserRegisterationDto
        {
            email = "[email protected]",
            msisdn = "24242455",
            externalUserId = "external-id"
        };

    // Call the RegisterUserAsync method
    var result = await userManagementService.RegisterUserAsync(userRegistrationDto);

    // Assert that the result is not null
    Assert.NotNull(result);

    // Assert that the result is success
    Assert.True(result.Succeeded);

    // Verify that CreateAsync was called with the expected AppUser
    userManagerMock.Verify(x => x.CreateAsync(It.IsAny<AppUser>(), userRegistrationDto.email), Times.Once);
}

Server Manager:

public class UserManagementService : IUserManagementService
{
     private readonly UserManager<AppUser> _userManager;
     private readonly IMapper _mapper;

     public UserManagementService(UserManager<AppUser> userManager, IMapper mapper)
     {
         _userManager = userManager;
         _mapper = mapper;
     }

     public async Task<IdentityResult> RegisterUserAsync(UserRegisterationDto userRequest)
     {
         var appUser = _mapper.Map<UserRegisterationDto, AppUser>(userRequest);
         var result = await _userManager.CreateAsync(appUser);
         return result;
     }
}

Result from CreateAsync is always null.


Solution

  • UserManager has two overloads for CreateAsync, you are mocking wrong method.

    You need to use

    userManagerMock.Setup(x => x.CreateAsync(It.IsAny<AppUser>()))
        .ReturnsAsync(IdentityResult.Success);
    

    Moreover, your assertions for result do not make sense, as the result is whatever you define in mock. So you just verified if you have defined mock in a specific way, which is not subject for UT.

    The only corrrect assertion is to check whether CreateAsync was called with the right parameter.