NETCore3.1环境下使用NUnit运行器出现ReflectionTypeLoadException问题
关于NUnit .NET Core运行器程序集加载异常的说明与解决方案
缺陷确认
3.12-beta2版本的NUnit.ConsoleRunner.NetCore确实存在未正确处理AssemblyLoadContext.Resolving事件的缺陷。
当项目引用设置CopyLocal=false时,对应的依赖项不会被复制到输出目录,且测试程序集的.deps.json文件不会生成AssemblyLoadContext(ALC)直接加载所需的完整条目,此时ALC会触发Resolving事件请求外部解析依赖,但该版本NUnit运行器的自定义加载逻辑没有实现该事件的处理逻辑,后续调用assembly.GetTypes()时无法加载关联的依赖类型,就会抛出ReflectionTypeLoadException异常。
可落地的解决方案
- 升级NUnit运行器版本
该问题在v3.13及以上正式版的NUnit.ConsoleRunner.NetCore中已被官方修复,新版本补充了AssemblyLoadContext.Resolving事件的处理逻辑,会自动扫描测试程序集所在目录加载缺失的依赖,无需修改项目配置即可兼容CopyLocal=false的场景,是优先推荐的解决方案。 - 手动绑定ALC Resolving事件
如果暂时无法升级运行器版本,可以在测试项目的全局初始化逻辑中手动绑定事件处理,从固定目录加载缺失的程序集,示例代码如下:using NUnit.Framework; using System.Reflection; using System.Runtime.Loader; using System.IO; [SetUpFixture] public class GlobalTestSetup { [OneTimeSetUp] public void InitAssemblyResolver() { var currentAlc = AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()); currentAlc.Resolving += (alc, assemblyName) => { string dllPath = Path.Combine(AppContext.BaseDirectory, $"{assemblyName.Name}.dll"); return File.Exists(dllPath) ? alc.LoadFromAssemblyPath(dllPath) : null; }; } } - 配置依赖探测路径
可以在测试项目的运行配置文件中添加探测路径节点,指定所有依赖程序集所在的目录,让NUnit运行器加载时自动扫描对应路径的程序集,无需修改CopyLocal配置。 - 临时调整CopyLocal属性
若以上方案都不适用,可临时将测试项目依赖的引用CopyLocal属性设置为true,此时.deps.json会生成完整的加载条目,依赖程序集也会复制到输出目录,可直接绕过该加载问题。
内容的提问来源于stack exchange,提问作者Ian Spratt
相关产品推荐
相关产品推荐

