| name | migrating-to-mstest-sdk | ||||
|---|---|---|---|---|---|
| description | Migrates .NET test projects from the traditional MSTest setup (Microsoft.NET.Test.Sdk + MSTest.TestAdapter + MSTest.TestFramework) to MSTest.Sdk, the modern project SDK approach that bundles all testing infrastructure. Use when upgrading test projects, modernizing MSTest configuration, adopting MSTest Platform (MTP), or when users ask to "switch to MSTest.Sdk", "use latest MSTest", "migrate to MTP", or "update test project to MSTest SDK". Also relevant during .NET version upgrades when test projects are being modernized. | ||||
| metadata |
|
Migrate .NET test projects from the traditional package-based MSTest setup to MSTest.Sdk, a modern project SDK that consolidates testing infrastructure and provides Microsoft Testing Platform (MTP) capabilities.
Before (Traditional):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.*" />
<PackageReference Include="MSTest.TestAdapter" Version="3.*" />
<PackageReference Include="MSTest.TestFramework" Version="3.*" />
</ItemGroup>
</Project>After (MSTest.Sdk):
<Project Sdk="MSTest.Sdk/4.3.3">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<!-- MSTest packages now included in SDK -->
</Project>The SDK automatically includes:
- MSTest.TestAdapter (same version as SDK)
- MSTest.TestFramework (same version as SDK)
- Microsoft.Testing.Extensions.CodeCoverage (latest compatible)
- Microsoft.Testing.Extensions.TrxReport (latest compatible)
You no longer need to reference these packages explicitly.
Before migrating, confirm the SDK is accessible from your package sources:
# Test by creating a temporary project
dotnet new console -n TempTest -o C:\temp\mstestcheck
# Try adding MSTest.Sdk as a package to verify it's available
dotnet add C:\temp\mstestcheck\TempTest.csproj package MSTest.SdkIf the package resolves successfully, you can proceed. As of 2025, the current stable version is 4.3.3.
Version note: Check for newer versions on NuGet.org or your organization's package feed. The SDK version should match or exceed your current MSTest package versions.
Before making changes, capture the current state:
Copy-Item MyTestProject.csproj MyTestProject.csproj.backupThis allows easy rollback if issues arise.
Change the Sdk attribute from Microsoft.NET.Sdk to MSTest.Sdk/{version}:
<Project Sdk="MSTest.Sdk/4.3.3">The version in the SDK attribute pins the MSTest infrastructure to that specific release.
Delete these package references (they're now included in the SDK):
Microsoft.NET.Test.SdkMSTest.TestAdapterMSTest.TestFramework
Keep all other packages (test utilities, mocking frameworks, assertion libraries, application dependencies).
If your test project multi-targets (e.g., <TargetFrameworks>net8.0;net10.0</TargetFrameworks>):
- Change
<TargetFramework>(singular) to<TargetFrameworks>(plural) - MSTest.Sdk works across all target frameworks without conditional logic
- No framework-specific package references needed for the MSTest stack itself
Example:
<Project Sdk="MSTest.Sdk/4.3.3">
<PropertyGroup>
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
</PropertyGroup>
</Project>Remove built artifacts to ensure a clean slate:
Remove-Item obj -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item bin -Recurse -Force -ErrorAction SilentlyContinue
dotnet restore MyTestProject.csprojdotnet build MyTestProject.csprojExpected outcome: Clean build for all target frameworks with no errors.
Verify what the SDK brought in:
dotnet list MyTestProject.csproj packageYou should see MSTest.TestAdapter, MSTest.TestFramework, and testing extensions listed as dependencies, even though you didn't explicitly reference them.
dotnet test MyTestProject.csprojAll existing tests should pass without code changes. MSTest.Sdk is backward compatible with traditional MSTest test code.
Symptom:
error NU1605: Detected package downgrade: System.Security.Cryptography.Xml from 9.0.15 to 8.0.4
Cause: Transitive dependencies from your application packages may conflict with versions preferred by MSTest.Sdk.
Resolution: Add an explicit package reference for the higher version:
<ItemGroup>
<!-- Resolve version conflict by pinning to the newer version -->
<PackageReference Include="System.Security.Cryptography.Xml" Version="9.*" />
</ItemGroup>Replace System.Security.Cryptography.Xml with the actual conflicting package from your error message.
Symptom:
NETSDK1005: Assets file 'obj\project.assets.json' doesn't have a target for 'netX.0'
Cause: Stale obj folder from the previous SDK configuration.
Resolution:
Remove-Item obj -Recurse -Force
Remove-Item bin -Recurse -Force
dotnet restore
dotnet buildAlways clean before building after SDK changes.
Symptom: dotnet test reports zero tests found, but the test methods exist.
Cause: Rare compatibility issue with custom test adapters or third-party test frameworks.
Resolution:
- Verify
[TestClass]and[TestMethod]attributes are present - Check for conflicting test framework packages (xUnit, NUnit) in the same project
- Ensure test classes are
public - Try explicit restore:
dotnet restore --force
Symptom: NuGet can't resolve MSTest.Sdk during restore.
Cause: Your package source doesn't include MSTest.Sdk.
Resolution:
- Verify you have access to NuGet.org or a mirror that includes Microsoft packages
- Check your
nuget.configfor restricted sources - Temporarily test with NuGet.org directly:
dotnet restore --source https://api.nuget.org/v3/index.json
When test projects multi-target and some application dependencies need different versions per framework, use conditional item groups:
<Project Sdk="MSTest.Sdk/4.3.3">
<PropertyGroup>
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
</PropertyGroup>
<!-- Shared packages (work for all TFMs) -->
<ItemGroup>
<PackageReference Include="Moq" Version="4.*" />
<PackageReference Include="FluentAssertions" Version="6.*" />
</ItemGroup>
<!-- .NET 8 specific packages -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.*" />
</ItemGroup>
<!-- .NET 10 specific packages -->
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.*" />
</ItemGroup>
</Project>This pattern is useful when:
- Testing libraries that target a specific runtime version
- Application packages tied to framework versions (e.g., ASP.NET Core)
- Packages with breaking changes between major .NET versions
Skip migration if:
- Pinned to older MSTest versions - Your team explicitly requires MSTest 2.x for compatibility reasons
- Custom test adapters conflicting - You use proprietary test runners incompatible with MTP
- Legacy .NET Framework-only projects - MSTest.Sdk targets .NET Core/5+ scenarios; stick with packages for .NET Framework 4.x
- Corporate policy restrictions - Organization mandates package-based approach for auditing
After migration, verify:
- Project builds without warnings
- All target frameworks restore successfully
-
dotnet testdiscovers all tests - Test execution passes (same results as before)
- Code coverage collection works (if used)
- CI/CD pipelines complete successfully
- No package downgrade warnings (NU1605)
- Fewer package references - Three packages become one SDK declaration
- Version alignment - MSTest packages automatically stay in sync
- Microsoft Testing Platform - Built-in support for modern testing features
- Simplified maintenance - SDK version updates are centralized
- Multi-targeting friendly - No need to duplicate package references per TFM
Related skill:
managing-target-frameworks- Covers multi-targeting in depth Related skill:dotnet-version-upgrade- Often triggers test project modernization