.NET 6迁移:NUnit中如何加载子目录程序集?
解决NUnit测试中.NET 6加载子目录程序集的问题
方案1:带静态构造函数的SetUpFixture
创建一个完全不依赖子目录程序集的独立类,标记[SetUpFixture]后,利用静态构造函数的执行时机(早于单个测试类的OneTimeSetUp)注册程序集解析逻辑。NUnit会在测试启动阶段初始化这个类,确保解析逻辑提前生效。
示例代码:
using System; using System.IO; using System.Reflection; using NUnit.Framework; [SetUpFixture] public class AssemblyLoadingInitializer { static AssemblyLoadingInitializer() { AssemblyLoadContext.Default.Resolving += (context, assemblyName) => { // 定义子目录路径,基于测试程序集的输出目录 var subDirPath = Path.Combine(AppContext.BaseDirectory, "YourSubDirectory"); var assemblyPath = Path.Combine(subDirPath, $"{assemblyName.Name}.dll"); if (File.Exists(assemblyPath)) { return context.LoadFromAssemblyPath(assemblyPath); } return null; // 找不到则交给默认加载逻辑处理 }; } }
注意:这个类不需要任何测试方法,直接放在测试项目根命名空间下即可,避免延迟加载。
方案2:ModuleInitializer(.NET 5+适用)
如果测试项目基于.NET 6+,可以使用[ModuleInitializer]标记静态方法,这是.NET Runtime级别的初始化逻辑,执行时机早于所有NUnit特性,能彻底解决启动阶段的程序集加载问题。
示例代码:
using System; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; public static class AssemblyLoaderInitializer { [ModuleInitializer] public static void InitializeAssemblyLoading() { AssemblyLoadContext.Default.Resolving += (context, assemblyName) => { var subDirPath = Path.Combine(AppContext.BaseDirectory, "YourSubDirectory"); var assemblyPath = Path.Combine(subDirPath, $"{assemblyName.Name}.dll"); if (File.Exists(assemblyPath)) { return context.LoadFromAssemblyPath(assemblyPath); } return null; }; } }
关键注意事项
- 初始化类必须完全独立,不能引用任何需要从子目录加载的程序集,否则会触发初始化失败。
- 确保子目录和对应DLL被复制到测试输出目录,可在测试项目的
.csproj中添加配置:<ItemGroup> <Content Include="YourSubDirectory\*.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> </ItemGroup> - ReSharper测试运行器和TeamCity均支持上述两种方案,无需额外配置。
- 若子目录程序集存在依赖,需在
Resolving事件中递归处理依赖,或确保子目录包含所有关联DLL。
内容的提问来源于stack exchange,提问作者Alby87
相关产品推荐
相关产品推荐

