因此,我正在尝试使用xunit进行一些单元测试,并且我需要模拟一个接口,其中存储库使用UserManager。我认为这里发生的事情是在进行单元测试时UserManager未被初始化,因为如果我运行App,它将运行良好。
IUserRepository接口:
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(仅索引):
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 = "[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;
}
}
所以问题是:在UserController上,我有
var listaRolesByUser = await _userRepository.GetRolesAsync(item);
,当应用正常运行时,但是当我运行测试时,GetRolesAsync()
方法返回null,或者listaRolesByUser
没有初始化。抱歉,如果这看起来有点令人困惑,我不知道这是否是正确的方法,但这是我到目前为止所学到的。
最佳答案
您需要在模拟对象上设置GetRolesAsync(item)
方法,否则moq将从其返回null。
因此,将其放在模拟用户存储库的声明下:
mockUserRepo.Setup(repo => repo.GetRolesAsync()).Returns(Task.FromResult(getUsersExpectedRoles()));
这应该确保您的getUsersExpectedRoles()方法的结果被返回而不是返回null,并且与您要模拟的用户类型相匹配。
通常,您必须明确声明要在moq对象上设置的方法。因此,测试目标调用的任何方法实际上都需要与之关联的设置。
关于c# - 在Moq上将接口(interface)与UserManager一起使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49136871/