.NET Core xUnit ClassFixture非硬编码获取内容根路径方案问询
解决方案:无硬编码获取ContentRoot并注入IHostingEnvironment
针对你在构建可复用BaseFixture时遇到的两个问题,我整理了以下可行的解决方案:
1. 无需硬编码自动获取ContentRoot路径
原来的方法依赖硬编码的解决方案名称,我们可以修改GetProjectPath方法,通过自动查找解决方案文件来避免硬编码,这种方式通用性更强:
修改后的GetProjectPath方法
private string GetProjectPath(Assembly startupAssembly) { var projectName = startupAssembly.GetName().Name; var applicationBasePath = PlatformServices.Default.Application.ApplicationBasePath; var directoryInfo = new DirectoryInfo(applicationBasePath); // 遍历目录,自动查找任意.sln文件,不再依赖硬编码名称 do { var solutionFiles = directoryInfo.GetFiles("*.sln"); if (solutionFiles.Any()) { // 找到解决方案目录后,拼接启动项目的路径 return Path.GetFullPath(Path.Combine(directoryInfo.FullName, projectName)); } directoryInfo = directoryInfo.Parent; } while (directoryInfo != null); throw new Exception($"无法从应用根路径 {applicationBasePath} 定位到解决方案根目录"); }
如果你的项目结构比较特殊(比如一个解决方案下有多个同名项目),还可以直接从启动程序集的位置推导源码路径(需确保项目开启调试符号):
private string GetProjectPath(Assembly startupAssembly) { var codeBaseUri = new Uri(startupAssembly.CodeBase); var assemblyPath = Uri.UnescapeDataString(codeBaseUri.AbsolutePath); var assemblyDirectory = Path.GetDirectoryName(assemblyPath); // 从程序集输出目录回溯到项目源码目录(示例针对.NET Core标准输出结构) return Directory.GetParent(assemblyDirectory).Parent.Parent.FullName; }
2. 在BaseFixture中获取IHostingEnvironment
你不需要手动注入IHostingEnvironment,TestServer构建完成后,直接从其服务容器中解析即可。我们可以在BaseFixture中添加对应属性并初始化:
更新后的BaseFixture完整代码
public class BaseFixture<TStartup> : IDisposable where TStartup : class { public BaseFixture() { var startupAssembly = typeof(TStartup).GetTypeInfo().Assembly; var projectPath = GetProjectPath(startupAssembly); var host = new WebHostBuilder() .UseContentRoot(projectPath) .UseStartup(typeof(TStartup)); Server = new TestServer(host); Client = Server.CreateClient(); // 从TestServer的服务容器中解析IHostingEnvironment HostingEnvironment = Server.Host.Services.GetRequiredService<IHostingEnvironment>(); } private string GetProjectPath(Assembly startupAssembly) { var projectName = startupAssembly.GetName().Name; var applicationBasePath = PlatformServices.Default.Application.ApplicationBasePath; var directoryInfo = new DirectoryInfo(applicationBasePath); do { var solutionFiles = directoryInfo.GetFiles("*.sln"); if (solutionFiles.Any()) { return Path.GetFullPath(Path.Combine(directoryInfo.FullName, projectName)); } directoryInfo = directoryInfo.Parent; } while (directoryInfo != null); throw new Exception($"无法从应用根路径 {applicationBasePath} 定位到解决方案根目录"); } public TestServer Server { get; set; } public HttpClient Client { get; } public IHostingEnvironment HostingEnvironment { get; private set; } // 新增环境属性 public void Dispose() { Server.Dispose(); Client.Dispose(); } }
后续在继承BaseFixture的测试类中,你可以直接使用HostingEnvironment属性获取环境信息(比如内容根路径、环境名称等),完全摆脱硬编码的限制。
内容的提问来源于stack exchange,提问作者developer9969
相关产品推荐
相关产品推荐

