如何将测试依赖配置迁移至NuGet包且不破坏.NET单元测试发现?
我们的解决方案包含大量单元/集成测试项目,目前每个项目都单独维护自身的测试依赖包,典型配置如下:
<ItemGroup> <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="6.0.27" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" /> <PackageReference Include="xunit" Version="2.7.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.5.7"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference> <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> </ItemGroup>
我们已开发了一个包含测试框架依赖及测试编写辅助共享代码的NuGet包,希望将上述测试依赖整合到该包中。但移除项目内的依赖配置并引用此NuGet包后,单元测试无法被正常发现。
目前我们通过解决方案根目录的Directory.Build.props实现了临时统一配置,内容如下:
<?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <IsTestProject>false</IsTestProject> </PropertyGroup> <PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.UT')) or $(MSBuildProjectName.EndsWith('.IT'))"> <IsTestProject>true</IsTestProject> </PropertyGroup> <PropertyGroup Condition="$(IsTestProject)"> <IsPackable>false</IsPackable> </PropertyGroup> <ItemGroup Condition="$(IsTestProject)" > <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="6.0.27" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" /> <PackageReference Include="xunit" Version="2.7.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.5.7"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference> <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> </ItemGroup> </Project>
该配置通过项目命名约定(*.UT为单元测试项目、*.IT为集成测试项目)自动为测试项目添加依赖,无需每个项目单独配置。现在想咨询:能否将此配置迁移至我们的测试NuGet包中,且不破坏单元测试的发现功能?
解决方案:可以实现,通过NuGet的MSBuild注入机制完成迁移
1. 在测试NuGet包中添加MSBuild Props文件
在你的测试NuGet包项目中,创建build文件夹,新增一个与包名同名的.props文件(例如:若包名为YourCompany.TestingUtilities,则文件名为YourCompany.TestingUtilities.props),将原Directory.Build.props中的核心逻辑复制进去:
<?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- 根据项目名标记测试项目 --> <PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.UT')) or $(MSBuildProjectName.EndsWith('.IT'))"> <IsTestProject>true</IsTestProject> </PropertyGroup> <!-- 测试项目默认不允许打包 --> <PropertyGroup Condition="$(IsTestProject)"> <IsPackable>false</IsPackable> </PropertyGroup> <!-- 为测试项目添加统一依赖 --> <ItemGroup Condition="$(IsTestProject)"> <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="6.0.27" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" /> <PackageReference Include="xunit" Version="2.7.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.5.7"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference> <!-- 注意:DotNetCliToolReference已被弃用,建议改用dotnet tool install xunit.runner.console --> <!-- <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> --> </ItemGroup> </Project>
2. 配置NuGet包的打包规则
在测试NuGet包项目的.csproj文件中添加以下配置,确保build文件夹下的props文件被正确打包到NuGet包的build目录(这是NuGet识别MSBuild注入文件的标准位置):
<ItemGroup> <None Include="build/**/*"> <Pack>true</Pack> <PackagePath>build</PackagePath> </None> </ItemGroup>
3. 确保测试发现功能正常的关键细节
- Microsoft.NET.Test.Sdk必须被正确引用:它是测试发现和运行的核心依赖,缺少它测试运行器无法识别测试项目。
- 保留xunit.runner.visualstudio的资产配置:
PrivateAssets="all"确保该依赖不会被传递到其他引用此NuGet包的项目,IncludeAssets配置保证它能在测试项目中生效,提供Visual Studio测试发现支持。 - 弃用DotNetCliToolReference:该元素已被.NET Core 3.0+弃用,建议改用全局工具安装:
dotnet tool install -g xunit.runner.console,或者直接使用dotnet test命令(该命令会自动调用xunit测试运行器)。
4. 迁移后的使用方式
移除所有测试项目中的原有依赖配置,以及解决方案根目录的Directory.Build.props中的相关测试配置,只需在测试项目中添加对该NuGet包的引用即可:
<PackageReference Include="YourCompany.TestingUtilities" Version="1.0.0" />
NuGet会自动导入包中的.props文件,根据项目名判断是否为测试项目,并自动注入所需的测试依赖,同时保证测试能被正常发现和运行。
内容的提问来源于stack exchange,提问作者Kindanam

