如何针对已安装的Target Framework编译并执行测试?
条件适配.NET 6.0/7.0 Docker镜像的项目配置方案
问题背景
这个问题和Stack Overflow上的《How do I conditionally build .Net Core 3.0 only if supported by tooling?》重复,但现有方案不适用。需求是让项目能在.NET 6.0和7.0的官方Docker SDK镜像中自动适配构建,原尝试的配置完全无效:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup Condition="'$(VisualStudioVersion)'=='16.0'"> <TargetFramework>net6.0</TargetFramework> </PropertyGroup> <PropertyGroup Condition="'$(VisualStudioVersion)'=='17.0'"> <TargetFrameworks>net7.0</TargetFrameworks> </PropertyGroup>
环境信息
- .NET 6.0 SDK镜像:
% docker run -t mcr.microsoft.com/dotnet/sdk:6.0 dotnet --list-sdks 6.0.410 [/usr/share/dotnet/sdk] % docker run -t mcr.microsoft.com/dotnet/sdk:6.0 dotnet build --version MSBuild version 17.3.2+561848881 for .NET 17.3.2.46306
- .NET 7.0 SDK镜像:
% docker run -t mcr.microsoft.com/dotnet/sdk:7.0 dotnet --list-sdks 7.0.305 [/usr/share/dotnet/sdk] % docker run -t mcr.microsoft.com/dotnet/sdk:7.0 dotnet build --version MSBuild version 17.6.3+07e294721 for .NET 17.6.3.22601
核心问题:原方案失效+跨版本测试失败
原配置为什么没用?
原配置依赖VisualStudioVersion变量,但Docker SDK镜像里根本没装Visual Studio,这个变量要么不存在,要么值和预期不符,条件判断完全不触发。.NET7镜像构建.NET6项目测试失败的原因
.NET7 SDK支持向下编译.NET6项目,但镜像里只带了.NET7 runtime,测试时需要.NET6 runtime来运行testhost,所以构建能过,测试直接报错。复现步骤和输出如下:
复现步骤
% docker run -it mcr.microsoft.com/dotnet/sdk:7.0 # cd /tmp # dotnet new sln -o unit-testing-using-dotnet-test # cd unit-testing-using-dotnet-test # dotnet new classlib -o PrimeService # mv PrimeService/Class1.cs PrimeService.cs # dotnet sln add ./PrimeService/PrimeService.csproj # dotnet new xunit -o PrimeService.Tests # dotnet add ./PrimeService.Tests/PrimeService.Tests.csproj reference ./PrimeService/PrimeService.csproj # dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj
修改项目为net6.0:
# sed -e 's/net7.0/net6.0/' -i ./PrimeService/PrimeService.csproj # sed -e 's/net7.0/net6.0/' -i ./PrimeService.Tests/PrimeService.Tests.csproj
构建结果(成功)
# dotnet build MSBuild version 17.6.3+07e294721 for .NET Determining projects to restore... Restored /tmp/unit-testing-using-dotnet-test/PrimeService/PrimeService.csproj (in 696 ms). Restored /tmp/unit-testing-using-dotnet-test/PrimeService.Tests/PrimeService.Tests.csproj (in 752 ms). PrimeService -> /tmp/unit-testing-using-dotnet-test/PrimeService/bin/Debug/net6.0/PrimeService.dll PrimeService.Tests -> /tmp/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll Build succeeded. 0 Warning(s) 0 Error(s) Time Elapsed 00:00:03.71
测试结果(失败)
# dotnet test Determining projects to restore... All projects are up-to-date for restore. PrimeService -> /tmp/unit-testing-using-dotnet-test/PrimeService/bin/Debug/net6.0/PrimeService.dll PrimeService.Tests -> /tmp/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll Test run for /tmp/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll (.NETCoreApp,Version=v6.0) Microsoft (R) Test Execution Command Line Tool Version 17.6.0 (x64) Copyright (c) Microsoft Corporation. All rights reserved. Starting test execution, please wait... A total of 1 test files matched the specified pattern. Testhost process for source(s) '/tmp/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll' exited with error: You must install or update .NET to run this application. App: /tmp/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/testhost.dll Architecture: x64 Framework: 'Microsoft.NETCore.App', version '6.0.0' (x64) .NET location: /usr/share/dotnet/ The following frameworks were found: 7.0.8 at [/usr/share/dotnet/shared/Microsoft.NETCore.App] Learn about framework resolution: https://aka.ms/dotnet/app-launch-failed To install missing framework, download: https://aka.ms/dotnet-core-applaunch?framework=Microsoft.NETCore.App&framework_version=6.0.0&arch=x64&rid=debian.11-x64 . Please check the diagnostic logs for more information. Test Run Aborted.
解决方案
方案1:基于SDK版本动态设置单目标框架
用$(NETCoreSdkVersion)变量判断当前SDK主版本,自动切换目标框架,适配Docker环境:
<Project Sdk="Microsoft.NET.Sdk"> <!-- 默认目标为net6.0,可根据需求调整 --> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> </PropertyGroup> <!-- 当SDK版本是7.x及以上时,切换到net7.0 --> <PropertyGroup Condition="$([System.Version]::Parse('$(NETCoreSdkVersion)')).Major >= 7"> <TargetFramework>net7.0</TargetFramework> </PropertyGroup> </Project>
方案2:多目标框架+条件过滤(可选)
如果需要保留多目标声明,但只编译当前环境支持的框架:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <!-- 先声明所有支持的框架 --> <TargetFrameworks>net6.0;net7.0</TargetFrameworks> <!-- SDK6环境只编译net6.0 --> <TargetFrameworks Condition="$([System.Version]::Parse('$(NETCoreSdkVersion)')).Major == 6">net6.0</TargetFrameworks> <!-- SDK7环境只编译net7.0 --> <TargetFrameworks Condition="$([System.Version]::Parse('$(NETCoreSdkVersion)')).Major == 7">net7.0</TargetFrameworks> </PropertyGroup> </Project>
补充:如果必须在.NET7镜像中测试.NET6项目
可以在Dockerfile中安装.NET6 runtime,解决测试依赖问题:
FROM mcr.microsoft.com/dotnet/sdk:7.0 # 安装.NET6 runtime(Debian/Ubuntu镜像适用) RUN apt-get update && apt-get install -y dotnet-runtime-6.0
内容的提问来源于stack exchange,提问作者malat
相关产品推荐
相关产品推荐

