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

C# .NET注册控制器单元测试报错修复求助:ArgumentNullException

修复C# .NET RegistrationController单元测试的ArgumentNullException问题

错误原因

报错信息明确指向System.ArgumentNullException : Value cannot be null. (Parameter 'optionsAccessor'),根源是你在SetUp方法中创建UserClaimsPrincipalFactory<User>时,第二个参数传了null,而该构造函数要求optionsAccessor必须是非空值。

修复步骤及完整代码

除了修复optionsAccessor的问题,还要补充初始化其他未赋值的依赖(_configMock、_authMessageSenderOptions),同时建议使用内存数据库替代真实DbContext,避免测试影响真实数据:

using employmently_be.Data.Models;
using employmently_be.DbContexts;
using employmently_be.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NUnit.Framework;
using System.Threading.Tasks;
using employmently_be.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Moq;
using Microsoft.AspNetCore.Http;

namespace Employmently.Tests.Controllers
{
    [TestFixture]
    public class RegistrationControllerTests
    {
        private RegistrationController _registrationController;
        private UserManager<User> _userManager;
        private ILogger<EmailSender> _logger;
        private dbContext _dbContext;
        private IConfiguration _configMock;
        private IOptions<AuthMessageSenderOptions> _authMessageSenderOptions;

        [SetUp]
        public void SetUp()
        {
            // 1. 使用内存数据库创建DbContext,避免依赖真实数据库
            var dbContextOptions = new DbContextOptionsBuilder<dbContext>()
                .UseInMemoryDatabase(databaseName: "TestEmploymentlyDb")
                .Options;
            _dbContext = new dbContext(dbContextOptions);

            // 2. 创建UserStore和UserManager,补全必要依赖
            var userStore = new UserStore<User>(_dbContext);
            var identityOptions = Options.Create(new IdentityOptions());
            var userManagerLogger = Mock.Of<ILogger<UserManager<User>>>();
            _userManager = new UserManager<User>(
                userStore,
                identityOptions,
                new PasswordHasher<User>(),
                new[] { new UserValidator<User>() },
                new[] { new PasswordValidator<User>() },
                new UpperInvariantLookupNormalizer(),
                new IdentityErrorDescriber(),
                null,
                userManagerLogger
            );

            // 3. 修复UserClaimsPrincipalFactory的实例化,传入合法的optionsAccessor
            var claimsFactory = new UserClaimsPrincipalFactory<User>(_userManager, identityOptions);

            // 4. 初始化缺失的依赖
            _configMock = new Mock<IConfiguration>().Object;
            _authMessageSenderOptions = Options.Create(new AuthMessageSenderOptions());
            _logger = new LoggerFactory().CreateLogger<EmailSender>();

            // 5. 实例化RegistrationController
            _registrationController = new RegistrationController(
                _dbContext,
                _userManager,
                _configMock,
                _logger,
                _authMessageSenderOptions
            );
        }

        [TearDown]
        public void TearDown()
        {
            // 清理内存数据库
            _dbContext.Database.EnsureDeleted();
            _dbContext.Dispose();
        }

        [Test]
        public async Task Register_ValidModel_ReturnsSuccessResult()
        {
            // Arrange
            var model = new RegisterDto
            {
                Email = "testuser@test.com",
                Password = "Test1234!",
                ConfirmPassword = "Test1234!"
            };

            // Act
            var result = await _registrationController.Register(model);

            // Assert
            Assert.IsNotNull(result);
            Assert.IsInstanceOf<OkResult>(result);
        }
    }
}

关键修复点说明

  • UserClaimsPrincipalFactory实例化:传入了identityOptions(通过Options.Create(new IdentityOptions())创建的合法实例),不再传null。
  • 内存数据库:使用UseInMemoryDatabase创建临时测试数据库,测试完成后在TearDown中清理,避免数据残留。
  • 依赖补全:初始化了_configMock和_authMessageSenderOptions,避免控制器实例化时出现其他空引用异常。
  • UserManager优化:添加了必要的验证器(UserValidator、PasswordValidator),让测试更接近真实环境的行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 13:08:19