编写依赖User Manager的Account Service单元测试时无法获取Application User
问题:单元测试中无法获取Application User以添加声明
我正在为依赖User Manager和Sign Manager的Account Service编写单元测试,已Mock了UserManager、SignInManager和AccountRepository,但无法获取Application User来添加声明,用户始终为Null。相关代码如下:
Account Service代码及构造函数
IAccountRepository _accountRepo; public AccountService(IAccountRepository accountRepo) { _accountRepo = accountRepo; } public Task<bool> AddClaim(ApplicationUser user, Claim claim) { return _accountRepo.AddClaim(user, claim); }
Account Repository代码及构造函数
ApplicationDbContext _context; SignInManager<ApplicationUser> _signInManager; UserManager<ApplicationUser> _userManager; RoleManager<IdentityRole> _roleManager; private readonly IHttpContextAccessor _Hcontext; public AccountRepository(ApplicationDbContext context, SignInManager<ApplicationUser> signInManager, UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager, IHttpContextAccessor Hcontext) { _context = context; _signInManager = signInManager; _userManager = userManager; _roleManager = roleManager; _Hcontext = Hcontext; }
public async Task<bool> AddClaim(ApplicationUser user, Claim claim) { var result=await _userManager.AddClaimAsync(user, claim); if (result.Succeeded) return true; else return false; } public Guid GetCurrentUserId() { return Guid.Parse(_Hcontext.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier)); } public async Task<ApplicationUser> GetCurrentUser() { var claimsPrincipal = _Hcontext.HttpContext.User; return await _userManager.GetUserAsync(claimsPrincipal); }
单元测试代码
[SetUp] public void Setup() { options = new DbContextOptionsBuilder<ApplicationDbContext>() .UseInMemoryDatabase(databaseName: "TestDbOR247") .Options; context = new ApplicationDbContext(options); ApplicationUser userNew = new ApplicationUser() { Cvr = 12345678, IsBusiness = true, CustomerNumber = 0, Type = 0 }; userNew.IsBusiness = true; userNew.Email = "I@gmail.com"; userNew.UserName = "Ikram@123"; userNew.Id = userId.ToString(); List<ApplicationUser> _users = new List<ApplicationUser>(); _users.Add(userNew); var mockUserStore = new Mock<IUserStore<ApplicationUser>>(); var _userManager = new Mock<UserManager<ApplicationUser>>(mockUserStore.Object, null, null, null, null, null, null, null, null); _userManager.Setup(x => x.DeleteAsync(It.IsAny<ApplicationUser>())).ReturnsAsync(IdentityResult.Success); _userManager.Setup(x => x.CreateAsync(userNew, "Abcd-1234")).ReturnsAsync(IdentityResult.Success); _userManager.Setup(x => x.UpdateAsync(It.IsAny<ApplicationUser>())).ReturnsAsync(IdentityResult.Success); var _signInManager = new Mock<SignInManager<ApplicationUser>>(_userManager.Object, Mock.Of<IHttpContextAccessor>(), Mock.Of<IUserClaimsPrincipalFactory<ApplicationUser>>(), null, null, null, null); var roleStore = new Mock<IRoleStore<IdentityRole>>(); var _roleManager= new Mock<RoleManager<IdentityRole>>( roleStore.Object, null, null, null, null); var mockHttpContextAccessor = new Mock<IHttpContextAccessor>(); mockHttpContextAccessor.Setup(o => o.HttpContext.User).Returns(It.IsAny<ClaimsPrincipal>()); //_accountRepository = new AccountRepository(context,_signInManager.Object,_userManager.Object,_roleManager.Object,mockHttpContextAccessor.Object); _accountRepository = new Mock<AccountRepository>(context, _signInManager.Object, _userManager.Object, _roleManager.Object, mockHttpContextAccessor.Object); //mockUserStore.Setup(x => x.CreateAsync(userNew, It.IsAny<CancellationToken>()).Result).Returns(It.IsAny<IdentityResult>); var data = context.AppUsers.ToList(); if(data.Count==0) { AddSampleDataIntoDatabase(); } var abc = context.Users.ToList(); var list=_accountRepository.Object.GetUsers(); //auto mapper configuration var mockMapper = new MapperConfiguration(cfg => { cfg.AddProfile(new ApplicationMapper()); }); var mapper = mockMapper.CreateMapper(); accountService = new AccountService(_accountRepository.Object); } [Test] public async Task AddClaim_UserNotNull_ReturnTrue() { ApplicationUser user = new ApplicationUser() { Cvr = 12345678, IsBusiness = true, CustomerNumber = 0, Type = 0 }; var user1 = accountService.GetUsers(); var claim = AllClaims[0]; //Act var result = await accountService.AddClaim(user, claim); //Assert Assert.That(result, Is.True); }
问题分析与解决步骤
1. 补全UserManager的AddClaimAsync方法Mock
AccountRepository.AddClaim依赖_userManager.AddClaimAsync,但测试中未对该方法做Mock配置,导致默认返回失败结果。需添加:
_userManager.Setup(x => x.AddClaimAsync(It.IsAny<ApplicationUser>(), It.IsAny<Claim>())) .ReturnsAsync(IdentityResult.Success);
2. 替换AccountRepository的Mock为真实实例
你当前Mock了AccountRepository类,这会跳过真实的业务逻辑,使测试失去意义。应直接实例化真实的AccountRepository,传入已Mock的依赖:
// 替换原Mock代码为真实实例 _accountRepository = new AccountRepository(context, _signInManager.Object, _userManager.Object, _roleManager.Object, mockHttpContextAccessor.Object);
3. 使用已初始化的用户对象进行测试
测试方法中新建的ApplicationUser未与UserManager关联,直接使用Setup中创建的userNew即可:
[Test] public async Task AddClaim_UserNotNull_ReturnTrue() { var claim = AllClaims[0]; // 使用Setup中已初始化的userNew var result = await accountService.AddClaim(userNew, claim); Assert.That(result, Is.True); }
4. (可选)修复GetCurrentUser的Mock逻辑
若需测试GetCurrentUser方法,需为IHttpContextAccessor返回包含用户ID声明的ClaimsPrincipal,同时MockUserManager.GetUserAsync:
// 在Setup中添加 var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, userId.ToString()) }; var identity = new ClaimsIdentity(claims, "TestAuth"); var claimsPrincipal = new ClaimsPrincipal(identity); mockHttpContextAccessor.Setup(o => o.HttpContext.User).Returns(claimsPrincipal); // Mock UserManager.GetUserAsync _userManager.Setup(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>())) .ReturnsAsync(userNew);
内容的提问来源于stack exchange,提问作者IkramK
相关产品推荐
相关产品推荐

