c# - 在 Moq 上使用与 UserManager 的接口(interface)

标签 c# asp.net-mvc entity-framework unit-testing asp.net-identity

所以,我正在尝试使用 xunit 进行一些单元测试,我需要模拟一个接口(interface),它的存储库使用 UserManager。我认为这里发生的事情是当我进行单元测试时 UserManager 没有被初始化,因为如果我运行应用程序它工作正常。

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();
    }

用户资料库:

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(只是索引):

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);
    }

和测试:

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 = "leonardo@teste.com",
                Email = "leonardo@teste.com",
                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;
        }
    }

所以问题是:在 UserController 上我有 var listaRolesByUser = await _userRepository.GetRolesAsync(item); 当应用程序运行正常时,但是当我运行测试时 GetRolesAsync() 方法返回 null,或者 listaRolesByUser 未初始化。

抱歉,如果这看起来有点困惑,我不知道这是否是正确的做法,但这是我目前学到的。

最佳答案

您需要在您的 mock 上设置 GetRolesAsync(item) 方法,否则 moq 只会从中返回 null。

所以把它放在模拟用户存储库的声明下面:

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

这应该确保返回 getUsersExpectedRoles() 方法的结果而不是 null,并且它与您要模拟的用户类型匹配。

一般而言,您必须明确声明要在最小起订量对象上设置的方法。因此,任何被测试目标调用的方法都需要与之关联的设置。

关于c# - 在 Moq 上使用与 UserManager 的接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49136871/

相关文章:

c# - 如何记录和跟踪 .net 应用程序的异常

c# - 属性值不反射(reflect)运行时所做的更改

c# - Ubuntu MATE ARM32 上的 Azure 语音 SDK 意图识别错误

asp.net - 如何在 Web 上下文中替换 OpenExeConfiguration (asp.net mvc 1)

c# - Entity Framework 和外键作为字符串

c# - DateTime ParseExact 抛出异常与 hh vs HH

javascript - 参数字典包含不可为 null 类型 'talepID' 的参数 'System.Int32' 的 null 条目

c# - 将 ASP.net 身份用户与其他表一起使用

c# - 如何在 ASP.NET MVC 5、Entity Framework 6 中使用流畅的 API 映射表?

asp.net-mvc - 使用Asp.Net C#MVC4和Json,如何使我的图表根据页面数据表进行更新