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

ASP.NET Core测试异常排查:CreateUser触发非预期Catch的解决问询

解决CreateAsync触发空引用异常的测试问题

看起来你在测试用户创建功能时遇到了空引用异常,而且异常被包装成了AggregateException,导致测试中途失败。我来帮你一步步排查和解决:

1. 核心问题:控制器的UserManager未正确初始化

你的测试代码里直接new UsersController(),但控制器依赖的UserManager<ApplicationUser>并没有被注入有效实例——UserManager本身需要依赖IUserStore、密码哈希器等多个服务,手动实例化控制器时这些依赖都是null,调用CreateAsync时自然会触发空引用。

修复方法:模拟或注入有效UserManager实例

用Moq框架模拟必要的依赖,给控制器提供可用的UserManager:

// 模拟IUserStore接口,实现CreateAsync的基本逻辑
var userStoreMock = new Mock<IUserStore<ApplicationUser>>();
userStoreMock.Setup(s => s.CreateAsync(It.IsAny<ApplicationUser>(), It.IsAny<CancellationToken>()))
             .ReturnsAsync(IdentityResult.Success);
userStoreMock.Setup(s => s.FindByIdAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
             .ReturnsAsync((string id, CancellationToken ct) => new ApplicationUser { Id = id });

// 创建UserManager实例,传入模拟的Store,其他非必需依赖传null即可
var userManager = new UserManager<ApplicationUser>(
    userStoreMock.Object, null, null, null, null, null, null, null, null
);

// 初始化控制器时传入这个userManager
var usersController = new UsersController(userManager);

同时确保你的控制器构造函数是依赖注入的形式:

public class UsersController : ControllerBase
{
    private readonly UserManager<ApplicationUser> _userManager;

    public UsersController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    // 你的CreateUser方法...
}

2. 检查ViewModel到Model的转换逻辑

虽然你说传入的参数非空,但要确认ModelConverter.ViewModelToModel.GetUser(userVM)是否返回了完整有效的ApplicationUser实例——比如UserName这类UserManager.CreateAsync必需的属性有没有被正确赋值?

可以在控制器里加个调试检查:

ApplicationUser user = ModelConverter.ViewModelToModel.GetUser(userVM);
Debug.Assert(user != null, "转换后的User实例不能为null");
Debug.Assert(!string.IsNullOrEmpty(user.UserName), "UserName是创建用户的必填属性");

3. 避免用.Result调用异步方法

测试里的.Result会把异步异常包装成AggregateException,不仅增加排查难度,还可能导致死锁。改成异步测试方法:

[Fact]
public async Task Should_AddShiftExchangeToUser()
{
    MPContext context = CleanContext();
    var usersController = new UsersController(userManager); // 用上面初始化好的userManager

    try
    {
        var x = await usersController.CreateUser(new ViewModels.UserVM());
        var y = await usersController.CreateUser(new ViewModels.UserVM());
        var result = await usersController.AddShiftExchange(
            new ShiftExchangeVM() { RequesterId = x.Value, ReceiverId = y.Value }, 
            x.Value
        );
        
        Assert.NotNull(result.Value);
        ShiftExchange shiftExchange = await context.shiftExchanges.FirstOrDefaultAsync(s => s.Id == result.Value);
        
        Assert.NotNull(shiftExchange);
        Assert.NotNull(shiftExchange.Receiver);
        Assert.NotNull(shiftExchange.Requester);
    }
    catch (Exception ex)
    {
        Assert.Null(ex);
    }
}

这样如果有异常,你能直接看到原始的异常类型,不用再拆解AggregateException。

4. 验证CleanContext()返回的DbContext

确保CleanContext()返回的MPContext是完全初始化的,shiftExchanges DbSet已经正确配置,避免后续查询时出现空引用。


内容的提问来源于stack exchange,提问作者Samantha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:36:00