.NET 6迁移后单元测试无法读取XML格式App.config配置问题
问题根因
.NET 6 归属于统一后的.NET Core技术栈,ConfigurationManager的默认配置加载逻辑和传统.NET Framework存在区别:组件默认只会读取当前进程入口EXE同名的.config文件。
单元测试场景下的实际运行入口是测试框架自带的testhost.exe,因此默认只会查找同目录下的testhost.exe.config,不会自动加载测试程序集生成的xxx.dll.config,这就是配置读取为空的核心原因。主EXE项目能正常加载配置,是因为EXE本身就是进程入口,编译生成的配置名和入口EXE匹配,不存在识别偏差。
可行解决方案
按改动成本从低到高排列:
- 编译期自动重命名配置文件(零业务代码改动,最适配当前保留XML配置的需求)
操作步骤:- 右键单元测试项目中的
App.config文件,打开属性面板,将「复制到输出目录」选项设置为如果较新则复制 - 右键编辑单元测试项目的
.csproj文件,在<Project>节点内追加如下编译配置,实现编译后自动将测试DLL对应的配置文件复制为测试运行器可识别的文件名:
配置完成后重新生成项目,无论是ReSharper测试运行器、VS自带测试工具还是<Target Name="AdaptTestConfig" AfterTargets="Build"> <Copy SourceFiles="$(OutDir)$(AssemblyName).dll.config" DestinationFiles="$(OutDir)testhost.exe.config" /> </Target>dotnet test命令行,都能正常通过ConfigurationManager读取到AppSettings节点的内容。 - 右键单元测试项目中的
- 测试初始化阶段显式加载配置
如果不想修改项目编译配置,可以在单元测试项目中添加全局初始化逻辑,在所有测试执行前手动指定要加载的配置文件路径。NUnit下可以通过[SetUpFixture]特性实现程序集级一次性初始化,示例代码:using System.Configuration; using System.Reflection; [SetUpFixture] public class GlobalTestInit { [OneTimeSetUp] public void LoadAppConfig() { string testAssemblyPath = Assembly.GetExecutingAssembly().Location; string configFileTarget = Path.ChangeExtension(testAssemblyPath, ".dll.config"); // 注意OpenExeConfiguration入参需去掉.config后缀 ConfigurationManager.OpenExeConfiguration(configFileTarget.Replace(".config", string.Empty)); } } - 多测试运行器兼容配置
如果你日常会切换使用不同的测试工具(比如ReSharper自带运行器、VS测试资源管理器、命令行dotnet test),可以在上述编译Target中追加多条复制规则,同时生成ReSharperTestRunner.exe.config等常见测试入口对应的配置文件,一次配置即可适配所有运行场景。
补充提示:后续如果完成XML配置到JSON格式appsettings的迁移,只需要在测试初始化逻辑中手动构建
IConfiguration实例即可,不需要再依赖ConfigurationManager的默认加载规则,适配会更灵活。
内容的提问来源于stack exchange,提问作者AFract
相关产品推荐
相关产品推荐

