You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编写依赖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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 00:55:20