我有一个超过平均水平的复杂(我怀疑)解决方案,在升级到dotnet sdk 1.1和Visual Studio 2017之后,我无法从命令行构建和测试。
它一直在VS 2015中使用dotnet sdk 1.0.0-preview2-003131,因此它在我们的构建服务器上的VS 2015和命令行中构建和运行。
但升级到VS 2017后我遇到了一些问题。
概述设置。 我有一个大致如下所示的解决方案(现实生活中的更多项目)
MySolution.sln
在VS 2015中,这是通过在Git中存储restore.dg和project.fragment.lock.json来实现的,然后我可以运行dotnet restore,然后运行dotnet build和dotnet test。
升级到VS 2017后,当我从Visual Studio构建和运行时,一切正常。 (迁移对基础项目的引用有一些麻烦 - 但删除了那些,并在迁移后重新读取,然后一切都很好)
'dotnet restore mySolution.sln'工作正常。它正确地恢复了WebApi和TestProject的包 - 并且与预览位相反,开箱即用。我不得不摆弄恢复和片段文件。
但是,如果我运行'dotnet build MySolution.sln -f net452 -r win10-x86',我会收到一堆构建错误。
如果我运行'dotnet msbuild MySolution.sln -f net452 -r win10-x86'就行了。
在这样的解决方案中,这是从CLI工具构建的正确方法吗?
因此,对于构建和恢复,我可以从CLI和VS 2017中使用它。并且具有相同的结果。
但是对于测试,一致性会停止。
我可以在Visual Studio Test Explorer中运行测试。 Unittests运行良好,绿色。但是,我启动TestServer的集成测试失败,引用不匹配Microsoft.Extensions.DependencyInjection.Abstractions 1.0.0和1.1.0。
因此,测试链中的某些内容需要1.0.0的程序集,但在调试目录中只能找到1.1.0。
这可以通过程序集重定向来解决 - 但是相当多的程序集似乎是错误的/不匹配的。
如果我运行'dotnet test --no-build TestProject / TestProject.csproj',测试都是绿色的 - 没有问题。
如此突出的问题:
我希望我能够彻底解释(但又简单易懂)。
如果需要更多信息来了解该方案,请告诉我们。
最诚挚的问候 安德斯
答案 0 :(得分:10)
好的,经过一些艰苦的思考/挖掘时间后,我想我找到了合适的解决方案。
将在此处发布以供参考。
对dotnet cli问题的交叉引用:https://github.com/dotnet/cli/issues/6032
我有一个现有的遗留解决方案,可以构建到.Net 4.5,x86,让它称之为oldsolution.sln
我有一个新的解决方案,其中包含来自 oldsolution.sln 的一些项目,以及一些新的dotnet核心项目,我们称之为 mySolution.sln 。
新解决方案还需要构建到x86 for .Net 4.5
<强>建筑强>
这里要掌握的关键是Visual Studio 2017使用安装文件夹中的msbuild.exe来构建。 dotnet msbuild 使用dotnet sdk文件夹中的程序集。这些并不相同。
因此要像Visual Studio一样构建,我必须找到正确使用的msbuild可执行文件。
Visual Studio团队已经开发了一个工具(https://www.nuget.org/packages/vswhere),我在构建脚本中使用它。
随着一切的到位,一切正常。 (建立明智)
下面是我的PSake脚本,用于构建和测试解决方案。
Task BuildApi {
exec { msbuild ./oldSolution.sln /t:Rebuild /p:Configuration="Release" /p:Platform=x86 /m /verbosity:minimal /nr:false }
exec { dotnet restore .\mySolution.sln }
#Find location of VS2017
$VsPath = .\packages\vswhere.1.0.50\tools\vswhere.exe -latest -property installationPath
$msBuild17 = "$vsPath\MSBuild\15.0\Bin\MSBuild.exe"
exec { &$msbuild17 ./mySolution.sln /t:Build /p:Configuration=Release /p:Platform=x86 /m /verbosity:minimal /nr:false }
}
Task TestApi -depends BuildApi{
if(!(Test-Path TestResults))
{
mkdir TestResults
}
if(!(Test-Path TestResults/coverage))
{
mkdir TestResults/coverage
}
$coverage = './packages/OpenCover.4.6.519/tools/OpenCover.Console.exe'
$target = "`"C:\Program Files (x86)\dotnet\dotnet.exe`""
$filter = "`"+[WebApi]*`""
#UnitTests
$targetargs = "`"test --no-build .\WebApi\test\WebApi.UnitTests\WebApi.UnitTests.csproj -c Release --logger `"trx;LogFileName=UnitTests.trx`"`""
$output = 'TestResults/coverage/WebApi.UnitTests.Coverage.xml'
&$coverage -register:user -oldstyle -target:$target -targetargs:$targetargs -output:$output -filter:$filter
# IntegrationTests
$targetargs = "`"test --no-build .\Web\test\WebApi.IntegrationTests\WebApi.IntegrationTests.csproj c Release --logger `"trx;LogFileName=IntegrationTests.trx`"`""
$output = 'TestResults/coverage/WebApi.IntegrationTests.Coverage.xml'
&$coverage -register:user -oldstyle -target:$target -targetargs:$targetargs -output:$output -filter:$filter
#Generate HTML report
$reportGenerator = "./packages/ReportGenerator.2.4.5.0/tools/ReportGenerator.exe"
$reportFiles = "TestResults/coverage/WebApi.UnitTests.Coverage.xml;TestResults/coverage/WebApi.IntegrationTests.Coverage.xml"
$targetDir = "./TestResults/coverage/WebApi"
&$reportGenerator -reports:$reportFiles -targetdir:$targetDir
}
到目前为止一切顺利。
<强>测试强>
然后我遇到麻烦让OpenCover拿起报道结果。
发现XUnit执行了shadowCopy - 修复此问题是在每个测试项目中放置一个xunit.runner.json(https://xunit.github.io/docs/configuring-with-json.html)
{
"shadowCopy": false
}
告诉XUnit不要进行卷影复制,因此OpenCover可以找到与正在测试的可执行文件匹配的PDB文件。
最后......
在Visual Studio中运行测试,所有使用Microsoft.AspNetCore.TestHost.TestServer引用某些dotnet核心程序集的测试失败,因为&#34;某些内容&#34;引用了v 1.0.0版本的程序集 - 我的项目引用了v 1.1.x.
我已经通过在app.config文件中为所有失败的程序集进行程序集重定向来修复此问题。没有设法找出使用旧的1.0.0程序集的人/用户 - 但是VS 2017构建链中的某些东西似乎也是这样 - 因为它与 dotnet test 一起使用。
但是,这是我的app.config的副本,其中重定向放置在我的集成测试项目中。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">"
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.DependencyInjection.Abstractions" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.AspNetCore.Mvc.Core" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.2.0" newVersion="1.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.Options" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.1.0" newVersion="1.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.AspNetCore.Http.Abstractions" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.1.0" newVersion="1.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.AspNetCore.StaticFiles" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.1.0" newVersion="1.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.FileProviders.Abstractions" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.Primitives" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.AspNetCore.Routing" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.1.0" newVersion="1.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.AspNetCore.Routing.Abstractions" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.1.0" newVersion="1.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.AspNetCore.Mvc.Formatters.Json" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.2.0" newVersion="1.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.AspNetCore.Mvc.ApiExplorer" culture="neutral" publicKeyToken="adb9793829ddae60" />
<bindingRedirect oldVersion="0.0.0.0-1.1.2.0" newVersion="1.1.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Phew ......这是一场激烈的战斗。
但它的价值在哪里。
与传统x86,网络4,5组件相结合的解决方案,在全新的.Net Core Web Api解决方案中运行 - 我很高兴.. :-)