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

单元测试时私有ConfigurationManager字段抛出空引用错误如何解决

错误原因
  • 直接触发空引用的原因:业务类的_connectionString字段采用内联初始化,在你实例化DatabaseReaderGateway时会直接调用ConfigurationManager.ConnectionStrings["Database"]读取连接字符串,此时测试项目的App.config未正确复制到测试运行目录,导致无法读取到名为Database的连接字符串节点,返回null后调用.ConnectionString触发空引用异常。
  • 隐含的架构问题:业务类没有采用依赖注入模式,硬编码了IDapperReaderWrapper的实例化逻辑和连接字符串读取逻辑,你在测试中构造的_mockDapperReaderWrapper没有被注入到业务类实例中,即使解决了连接字符串的报错,Mock逻辑也不会生效,测试无法正常通过。
解决方案

临时修复空引用问题

右键测试项目中的App.config文件,选择「属性」,将「复制到输出目录」的属性值修改为「始终复制」或「如果较新则复制」,确保测试运行时目录下存在正确的配置文件,ConfigurationManager可以读取到对应连接字符串。

推荐的单元测试友好改造方案

1. 改造业务类,改为依赖注入模式

移除业务类中硬编码的依赖初始化逻辑,通过构造函数传入外部依赖:

public class DatabaseReaderGateway
{
    private readonly string _connectionString;
    private readonly IDapperReaderWrapper _dapperReaderWrapper;

    public DatabaseReaderGateway(string connectionString, IDapperReaderWrapper dapperReaderWrapper)
    {
        _connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
        _dapperReaderWrapper = dapperReaderWrapper ?? throw new ArgumentNullException(nameof(dapperReaderWrapper));
    }

    /// <summary>
    /// Retrieves a list of admins from the database.
    /// </summary>
    /// <returns>List of admins.</returns>
    public List<Admin> RetrieveListOfAdmins()
    {
        var adminDatabaseReader = new AdminDatabaseReader(_connectionString, _dapperReaderWrapper);
        return adminDatabaseReader.GetAll();
    }
}

2. 修改测试初始化逻辑,注入Mock依赖

在测试初始化时将测试用连接字符串和Mock对象传入业务类构造函数:

[TestInitialize]
public void Initialize()
{
    _connectionString = DatabaseShared.GetTestingConfigurationFile();
    _mockDapperReaderWrapper = new Mock<IDapperReaderWrapper>();
    // 注入测试依赖
    _databaseReaderGateway = new DatabaseReaderGateway(_connectionString, _mockDapperReaderWrapper.Object);
}

3. 修复断言逻辑

原测试中使用Assert.AreEqual比较两个列表默认是比较引用地址,无法校验列表内容是否一致,改为集合校验:

// 替换原有的AreEqual断言
CollectionAssert.AreEqual(expectedListOfAdmins, actualListOfAdmins, "我们期望列表内容一致,但实际不一致。");

可选优化:简化连接字符串读取逻辑

直接按名称读取连接字符串,无需遍历:

public static string GetTestingConfigurationFile()
{
    ExeConfigurationFileMap configFileMap = new()
    {
        ExeConfigFilename = "App.config"
    };
    var config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
    return config.ConnectionStrings.ConnectionStrings["Database"].ConnectionString;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 18:54:04