Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp .Net Core Unit Test Mock UserManager.CreateAsync and return Identity Result

Working on .Net Core Project and created below service to share common methods across the pages.

namespace MyApp.Tests.Services
{
    public class UserServiceTest
    {
        [Fact]
        public async Task CreateUser_ShouldCreateUser()
        {
            var user = new UserResponse
            {
                Id = "111",
                Email = "[email protected]",
                FirstName = "John",
                LastName = "Doe",
                CompanyName = "SomeCompany",
                PhoneNumber = "9123456789"
            };

            var appUser = new ApplicationUser
            {
                UserName = user.Email,
                Email = user.Email,
                FirstName = user.FirstName,
                LastName = user.LastName,
                CompanyName = user.CompanyName,
                PhoneNumber = user.PhoneNumber
            };

            var logger = Mock.Of<ILogger<UserService>>();
            var mockUserStore = new Mock<IUserStore<ApplicationUser>>();
            mockUserStore
                .Setup(x => x.CreateAsync(appUser, CancellationToken.None))
                .ReturnsAsync(IdentityResult.Success).Verifiable();

            // Tried this one as well but still getting null instead of IdentityResult
            // mockUserStore
            //     .Setup(x => x.CreateAsync(appUser, CancellationToken.None))
            //     .ReturnsAsync(new IdentityResultMock(true));

            var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
            var _userService = new UserService(userManager, logger);

            var result = await _userService.CreateUserInApp(user);

            Assert.True(result.Succeeded);
        }
    }

    public class IdentityResultMock : IdentityResult
    {
        public IdentityResultMock(bool succeeded) {
            base.Succeeded = succeeded;
         }
    }
}

Also wrote the Unit Test case for this service like below to test the UserService

namespace MyApp.Tests.Services
{
    public class UserServiceTest
    {
        [Fact]
        public async Task CreateUser_ShouldCreateUser()
        {
            var user = new UserResponse
            {
                Id = "111",
                Email = "[email protected]",
                FirstName = "John",
                LastName = "Doe",
                CompanyName = "SomeCompany",
                PhoneNumber = "9123456789"
            };

            var appUser = new ApplicationUser
            {
                UserName = user.Email,
                Email = user.Email,
                FirstName = user.FirstName,
                LastName = user.LastName,
                CompanyName = user.CompanyName,
                PhoneNumber = user.PhoneNumber
            };

            var logger = Mock.Of<ILogger<UserService>>();
            var mockUserStore = new Mock<IUserStore<ApplicationUser>>();
            mockUserStore
                .Setup(x => x.CreateAsync(appUser, CancellationToken.None))
                .ReturnsAsync(IdentityResult.Success).Verifiable(); ;

            var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
            var _userService = new UserService(userManager, logger);

            var result = await _userService.CreateUserInApp(user);

            Assert.True(result.Succeeded);
        }
    }
}

While running test in user service at

var createResult = await _userManager.CreateAsync(appUser);

createResult I am getting null due to this Test Case is failing and getting null reference exception. If I could return IdentityResult from mock CreateAsync setup then it will pass but not sure what wrong I am doing. Also Can not create object of IdentityResult because 'Succeeded' is protected and can not assign value explicitly. Please help. Thanks :)

like image 229
Ravi Avatar asked Sep 19 '25 11:09

Ravi


1 Answers

We need to see what is happening inside the constructor:

var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);

But not really. If you are testing the UserService here, then what you should be mocking is the UserManager and not it's internal dependency IUserStore.

Why is that? Becaus the internals of the UserManager might change and then you'll have to change both the UserManager tests and the UserService tests.

Mock the create of the UserManager as you do for the IUserStore and you'll see it was some other dependency in UserStore or somewhere totally outside the scope of the unit test.

Edit 1

I think I figured out your problem:

mockUserStore
    .Setup(x => x.CreateAsync(appUser, CancellationToken.None))
    .ReturnsAsync(IdentityResult.Success).Verifiable();

And the calling with

var result = await _userService.CreateUserInApp(user);

User object and appUser object are not the same, so the mocking framework does not return the expected value.

To make sure that this is the problem, try to mock with

mockUserStore
    .Setup(x => x.CreateAsync(It.IsAny<ApplicationUser>(), It.IsAny<CancellationToken>()))
    .ReturnsAsync(IdentityResult.Success).Verifiable();
like image 61
Athanasios Kataras Avatar answered Sep 22 '25 07:09

Athanasios Kataras