Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Interfaces with UserManager on Moq

So, I'm trying to do some unit testing with xunit, and I need to mock an interface where it's repository uses UserManager. I think what is happening here is that the UserManager is not getting initialized when I'm doing the unit tests, because if I run the App it works fine.

IUserRepository interface:

public interface IUserRepository : IDisposable
    {
        Task<List<ApplicationUser>> ToListAsync();
        Task<ApplicationUser> FindByIDAsync(string userId);
        Task<ApplicationUser> FindByNameAsync(string userName);
        Task<IList<string>> GetRolesAsync(ApplicationUser user);
        Task AddToRoleAsync(ApplicationUser user, string roleName);
        Task RemoveFromRoleAsync(ApplicationUser user, string roleName);
        Task<bool> AnyAsync(string userId);
        Task AddAsync(ApplicationUser user);
        Task DeleteAsync(string userId);
        void Update(ApplicationUser user);
        Task SaveChangesAsync();
    }

UserRepository:

public class UserRepository : IUserRepository
    {
        private readonly ApplicationDbContext _context;
        private readonly UserManager<ApplicationUser> _userManager;

        public UserRepository(ApplicationDbContext context, UserManager<ApplicationUser> userManager)
        {
            _context = context;
            _userManager = userManager;
        }

        public Task<ApplicationUser> FindByIDAsync(string userId)
        {
            return _context.ApplicationUser.FindAsync(userId);
        }

        public Task<ApplicationUser> FindByNameAsync(string userName)
        {
            return _context.ApplicationUser.SingleOrDefaultAsync(m => m.UserName == userName);
        }

        public Task<List<ApplicationUser>> ToListAsync()
        {
            return _context.ApplicationUser.ToListAsync();
        }

        public Task AddAsync(ApplicationUser user)
        {
            _context.ApplicationUser.AddAsync(user);
            return _context.SaveChangesAsync();
        }

        public void Update(ApplicationUser user)
        {
            _context.Entry(user).State = EntityState.Modified;
        }

        public Task DeleteAsync(string userId)
        {
            ApplicationUser user = _context.ApplicationUser.Find(userId);
            _context.ApplicationUser.Remove(user);
            return _context.SaveChangesAsync();
        }

        public Task<IList<string>> GetRolesAsync(ApplicationUser user)
        {
            return _userManager.GetRolesAsync(user);
        }

        public Task AddToRoleAsync(ApplicationUser user, string roleName)
        {
            _userManager.AddToRoleAsync(user, roleName);
            return _context.SaveChangesAsync();
        }

        public Task RemoveFromRoleAsync(ApplicationUser user, string roleName)
        {
            _userManager.RemoveFromRoleAsync(user, roleName);
            return _context.SaveChangesAsync();
        }

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    _context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public Task<bool> AnyAsync(string userId)
        {
            return _context.ApplicationUser.AnyAsync(e => e.Id == userId);
        }

        public Task SaveChangesAsync()
        {
            return _context.SaveChangesAsync();
        }
    }

UserController (Just the Index):

public class UserController : CustomBaseController
    {
        private readonly IUserRepository _userRepository;
        private readonly IRoleRepository _roleRepository;

        public UserController(IUserRepository userRepository,IRoleRepository roleRepository)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
        }

        // GET: User
        public async Task<IActionResult> Index()
        {
            List<ApplicationUser> ListaUsers = new List<ApplicationUser>();
            List<DadosIndexViewModel> ListaUsersModel = new List<DadosIndexViewModel>();
            List<Tuple<ApplicationUser, string>> ListaUserComRoles = new List<Tuple<ApplicationUser, string>>();
            var modelView = await base.CreateModel<IndexViewModel>(_userRepository);

            ListaUsers = await _userRepository.ToListAsync();

            foreach(var item in ListaUsers)
            {
                //Por cada User que existir na ListaUsers criar um objecto novo?
                DadosIndexViewModel modelFor = new DadosIndexViewModel();

                //Lista complementar para igualar a modelFor.Roles -> estava a dar null.
                var tempList = new List<string>();

                //Inserir no Objeto novo o user.
                modelFor.Nome = item.Nome;
                modelFor.Email = item.Email;
                modelFor.Id = item.Id;
                modelFor.Telemovel = item.PhoneNumber;

                //Buscar a lista completa de roles por cada user(item).
                var listaRolesByUser = await _userRepository.GetRolesAsync(item);

                //Por cada role que existir na lista comp
                foreach (var item2 in listaRolesByUser)
                    {
                        //Não é preciso isto mas funciona. Array associativo.
                        ListaUserComRoles.Add(new Tuple<ApplicationUser, string>(item, item2));
                        //Adicionar cada role à lista
                        tempList.Add(item2);
                    }
                modelFor.Roles = tempList;
                //Preencher um objeto IndexViewModel e adiciona-lo a uma lista até ter todos os users.
                ListaUsersModel.Add(modelFor);
            }
        //Atribuir a lista de utilizadores à lista do modelo (DadosUsers)
        modelView.DadosUsers = ListaUsersModel;
        //return View(ListaUsersModel);
        return View(modelView);
    }

And the Test:

public class UserControllerTest
    {
        [Fact]
        public async Task Index_Test()
        {

            // Arrange
            var mockUserRepo = new Mock<IUserRepository>();
            mockUserRepo.Setup(repo => repo.ToListAsync()).Returns(Task.FromResult(getTestUsers()));
            var mockRoleRepo = new Mock<IRoleRepository>();
            mockRoleRepo.Setup(repo => repo.ToListAsync()).Returns(Task.FromResult(getTestRoles()));

            var controller = new UserController(mockUserRepo.Object, mockRoleRepo.Object);

            controller.ControllerContext = new ControllerContext
            {
                HttpContext = new DefaultHttpContext
                {
                    User = new ClaimsPrincipal(new ClaimsIdentity())
                }
            };
            // Act
            var result = await controller.Index();

            // Assert
            var viewResult = Assert.IsType<ViewResult>(result);
            var model = Assert.IsAssignableFrom<IndexViewModel>(viewResult.ViewData.Model);
            Assert.Equal(2,model.DadosUsers.Count);
        }

        private List<ApplicationUser> getTestUsers()
        {
            var Users = new List<ApplicationUser>();

            Users.Add(new ApplicationUser()
            {
                Nome = "Leonardo",
                UserName = "[email protected]",
                Email = "[email protected]",
                PhoneNumber= "911938567"
            });

            Users.Add(new ApplicationUser()
            {
                Nome = "José",
                UserName = "José@teste.com",
                Email = "José@teste.com",
                PhoneNumber = "993746738"
            });

            return Users;
        }

        private List<IdentityRole> getTestRoles()
        {
            var roles = new List<IdentityRole>();

            roles.Add(new IdentityRole()
            {
                Name = "Admin",
                NormalizedName = "ADMIN"
            });
            roles.Add(new IdentityRole()
            {
                Name = "Guest",
                NormalizedName = "GUEST"
            });

            return roles;
        }
    }

So the problem is: On UserController I have var listaRolesByUser = await _userRepository.GetRolesAsync(item); and when the app it works fine, but when I'm running the test the GetRolesAsync() method returns null, or the listaRolesByUser doesn't get initialized.

Sorry if this looks a bit confusing, I don't know if this is the correct way of doing this but this is what I learned so far.

like image 415
Leonardo Henriques Avatar asked Oct 19 '25 15:10

Leonardo Henriques


1 Answers

You need to setup the GetRolesAsync(item) method on your mock or moq will just return null from it.

So put this just under the declaration for the mock user repository:

mockUserRepo.Setup(repo => repo.GetRolesAsync()).Returns(Task.FromResult(getUsersExpectedRoles()));

This should make sure that the result of your getUsersExpectedRoles() method gets returned instead of a null and it matches the user type you want to simulate.

As a general point, you do have to explicitly declare the methods you want to setup on an moq object. So any method that gets called by the test target, really needs a setup associated with it.

like image 129
gmn Avatar answered Oct 22 '25 05:10

gmn



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!