Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i mock i base method when test derived class

I have the problem that i want to write a unit test of a custom function in my user service. But this user service derives from asp.net core identity user manager. I want to extend the functionality of the user manager therefore i derived from it. So I want to test the method CreateCRohMUserAsync

    public class UserService : UserManager<User>, IUserService
{
    public UserService(IUserStore<User> store,
        IOptions<IdentityOptions> optionsAccessor,
        IPasswordHasher<User> passwordHasher,
        IEnumerable<IUserValidator<User>> userValidators,
        IEnumerable<IPasswordValidator<User>> passwordValidators,
        ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<User>> logger) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
    {
    }

    public async Task<IdentityResult> CreateCRohMUserAsync(User user)
    {
        PasswordGenerator pwGenerator = new PasswordGenerator();
        var password = pwGenerator.Generate();

        user.UserName = GetUniqueUserName(user.FirstName, user.LastName);

        var result = await base.CreateAsync(user, password);

        if (result.Succeeded)
        {
            //TODO: send mail to created user                
        }

        return result;
    }


    public string GetUniqueUserName(string firstName, string lastName)
    {
        if (string.IsNullOrEmpty(firstName))
        {
            throw new ArgumentNullException(nameof(firstName), "firstName can not be null");
        }
        if (string.IsNullOrEmpty(lastName))
        {
            throw new ArgumentNullException(nameof(lastName), "lastName can not be null");
        }

        return lastName + firstName.Substring(0, 2) + Users.Count() + 1;
    }
}

}

In my unit test i want to mock the base.CreateAsync(user,password) and the Users.Count() functionality of my base class. But I don't know how to do this. Or is my implementation wrong? How can I unit test this mehtod?

like image 827
Silvester Schn. Avatar asked Nov 28 '25 00:11

Silvester Schn.


1 Answers

Asumming you're using moq.

First you'll have to remove the base keyword in CreateCRohMUserAsync:

var result = await CreateAsync(user, password); // Previously base.CreateAsync

If it's present, the base class's implementation is always called - mocking CreateAsync will have no effect (moq mocks methods by overriding them).

After removing base, you can test CreateCRohMUserAsync like this:

[Fact]
public async void CreateCRohMUserAsync_DoesSomething()
{
    // Arrange
    ...
    Mock<UserService> mockTestSubject = new Mock<UserService>(...); // Pass services you'd normally pass to the UserService constructor
    mockTestSubject.CallBase = true; // So when you call CreateCRohMUserAsync, the logic you defined runs
    mockTestSubject.Setup(t => t.CreateAsync(...)).ReturnsAsync(...); // Mock CreateAsync
    // If GetUniqueUserName is virtual, you can mock it too    
    // mockTestSubject.Setup(t => t.GetUniqueUserName(...)).Returns(...);

    // Act
    IdentityResult result = await mockTestSubject.Object.CreateCRohMUserAsync(...);

    // Assert
    ...
}

The same pattern will work for GetUniqueUserName.

Essentially:

  • Mock your derived class so you can setup virtual members of your base class.
  • Set CallBase to true so you can run logic you defined in your derived class.
like image 107
JeremyTCD Avatar answered Nov 30 '25 14:11

JeremyTCD



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!