PAYATHON 2026

NuGet CPM 迁移后测试项目缺少 PackageReference,正常吗?

数据小陈

结论

仅在 Directory.Packages.props 中声明 <PackageVersion>,不足以让测试项目引用 Microsoft.NET.Test.Sdk。CPM 的常规做法是集中声明版本,再通过项目中的 <PackageReference Include="…" /> 声明依赖。NuGet CPM 文档

如果 .csproj 中没有看到引用,仍需检查共享配置或所用 SDK 是否已经添加了它。查明实际来源后,再决定是否补充。现有材料也不足以判断 CentralisedPackageConverter 删除该条目是否符合其具体版本的转换规则。

原配置中的 Update 是关键

迁移前的配置是:

<PackageReference Update="Microsoft.NET.Test.Sdk" Version="17.14.1" />

Update 用于修改已有 MSBuild item 的元数据,不会创建新的引用。如果该语句求值时没有匹配的 PackageReference,它就不会添加依赖。因此,原配置本身不能证明该包由 SampleTest.csproj 引入。MSBuild item 文档

可能是共享配置此前已经添加了引用,这一行只修改版本;也可能是这一行原本就没有匹配到引用。需要检查完整导入链才能确定。

依赖可能来自哪里?

优先检查以下位置:

  • Directory.Build.props、Directory.Build.targets 和其他导入的 .props、.targets 文件中,是否声明了 PackageReference Include="Microsoft.NET.Test.Sdk"。
  • 所用测试 SDK 是否自动添加了相关依赖。
  • Directory.Packages.props 是否还包含 GlobalPackageReference。它与普通 PackageVersion 不同,可以向适用项目添加全局包引用。全局包引用说明
  • 其他 NuGet 包是否通过依赖关系引入了它。传递依赖可以解释包为何出现,但包的存在本身不能证明测试所需的构建资产已正确生效。PackageReference 资产规则

这些来源都需要结合当前项目验证,暂时无法认定具体原因。

如何确认实际引用来源?

1. 重新还原并查看包列表

在项目所在目录执行:

dotnet restore SampleTest.csproj
dotnet list SampleTest.csproj package --include-transitive

查看 Microsoft.NET.Test.Sdk 是否出现,以及它被列为顶层包还是传递包。使用 .NET 10 SDK 时,也可以使用以下命令:包列表命令文档

dotnet package list --project SampleTest.csproj --include-transitive

如果 SDK 为 .NET 8.0.4xx 或更高版本,还可以查看具体依赖链:dotnet nuget why 文档

dotnet nuget why SampleTest.csproj Microsoft.NET.Test.Sdk

2. 检查 MSBuild 导入与求值结果

生成展开导入后的项目文件:

dotnet msbuild SampleTest.csproj -pp:expanded.xml

在 expanded.xml 中搜索 Microsoft.NET.Test.Sdk,结合导入边界和条件查找声明来源。该文件展示导入内容,其中的条件分支并不一定都已生效。

若所用 MSBuild 支持 -getItem,可以进一步查看求值后的引用项:

dotnet msbuild SampleTest.csproj -getItem:PackageReference

这两个参数分别用于展开导入和查看求值结果。MSBuild 命令行文档

排查时应使用与 CI 一致的配置和目标框架,避免条件引用造成差异。

3. 确认该项目的测试确实执行

解决方案构建成功只能证明构建通过;即使 CI 成功,也需要结合 SampleTest 项目的测试报告判断。检查该项目的发现数、执行数、跳过数和结果,确认没有遗漏整个项目。

如果使用 VSTest,可以单独检查:

dotnet test SampleTest.csproj --list-tests
dotnet test SampleTest.csproj --logger trx

以上参数适用于 VSTest;Microsoft.Testing.Platform 的命令选项应按对应运行方式确认。VSTest 命令文档

是否应该手动补回引用?

如果这是使用 VSTest 的常规 SDK 风格测试项目,且没有共享配置或测试 SDK 为它添加有效引用,建议补充以下配置。Microsoft.NET.Test.Sdk 为这类项目提供运行测试所需的测试平台支持。VSTest 项目说明

在现有 Directory.Packages.props 中保留版本声明,并确认已启用 CPM:

<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>
  <ItemGroup>
    <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
  </ItemGroup>
</Project>

在 SampleTest.csproj 的现有 <Project> 内添加:

<ItemGroup>
  <PackageReference Include="Microsoft.NET.Test.Sdk" />
</ItemGroup>

CPM 下无需在这个 PackageReference 上重复填写 Version。

如果求值结果已经包含共享配置提供的引用,就不必再次添加同名 Include。若仅依赖其他包间接引入,则需要考虑上游包升级后依赖发生变化的风险。

如果项目使用 Microsoft.Testing.Platform,应根据所用测试框架和 SDK 的要求判断。它与 VSTest 的运行方式存在区别,不能直接套用 VSTest 的依赖配置。测试平台迁移说明

完成调整后,在干净工作目录中重新还原并单独运行该测试项目,核对测试结果,确认配置是否有效。

备注:内容仅供参考。