.NET Core 2.1升级3.1后E2E测试中视图无法加载问题排查
这个问题其实是.NET Core 3.0+版本对Razor视图编译机制的调整导致的——在2.1版本中,Razor视图默认是编译到主应用程序集里的,而3.0之后,视图会被编译成独立的{YourAppName}.Views.dll程序集,你的测试环境刚好没加载这个程序集,或者运行时编译的路径没配置对,所以找不到视图。
结合你的场景,我整理了几个针对性的解决办法:
1. 加载视图程序集到测试的DI容器
你的TestStartup里只添加了控制器所在的程序集,却没把视图程序集加进去。可以在AddControllersWithViews链中补充添加视图程序集的ApplicationPart:
// 先获取视图程序集,你可以用视图里的任意生成类来定位,比如Login.cshtml对应的后台类 var viewsAssembly = typeof(YourApp.Views.Home.Login).Assembly; // 或者直接通过程序集名称加载 // var viewsAssembly = System.Reflection.Assembly.Load("YourApp.Views"); services.AddControllersWithViews(x => { x.Filters.Add(typeof(CustomExceptionFilter)); }) .AddNewtonsoftJson() .AddApplicationPart(typeof(HomeController).Assembly) .AddApplicationPart(viewsAssembly) // 新增这一行,把视图程序集加入进来 .AddControllersAsServices() .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
这样测试启动的应用就能找到预编译的视图了。
2. 确保测试环境下Razor运行时编译的路径正确
如果你的测试依赖视图的运行时编译(而不是预编译),那要注意测试进程的工作目录和手动启动时不一样——手动启动时工作目录是主应用的项目根,但测试运行时默认是测试项目的输出目录。
你可以在启动WebHost的时候指定正确的内容根:
var webHost = new WebHostBuilder() // 指向主应用的项目目录,根据你的项目结构调整路径 .UseContentRoot(Path.Combine(Directory.GetCurrentDirectory(), "../YourApp")) .UseStartup<TestStartup>() .Build();
或者在TestStartup中明确配置运行时编译的文件提供者:
services.AddRazorPages() .AddRazorRuntimeCompilation(options => { // 设置视图文件的物理路径,指向主应用的Views目录 options.FileProviders.Add(new PhysicalFileProvider( Path.Combine(Directory.GetCurrentDirectory(), "../YourApp/Views"))); });
3. 检查测试项目的引用
确保你的测试项目已经引用了主应用的视图程序集(YourApp.Views.dll),如果是通过项目引用的话,要保证这个程序集能被测试进程加载到。
为什么2.1版本没问题?
在.NET Core 2.1中,Razor视图默认是内嵌到主应用程序集里的,或者运行时编译的默认配置就能自动找到项目根目录的Views文件夹,所以测试启动时不需要额外配置。但3.0之后微软把视图编译独立成了单独的程序集,目的是优化发布体积和加载速度,这就导致测试环境需要手动处理视图程序集的加载问题了。
内容的提问来源于stack exchange,提问作者Joelty




