.net core VS 2017如何构建和测试包含.Net核心的混合解决方案

.net core VS 2017如何构建和测试包含.Net核心的混合解决方案,.net-core,visual-studio-2017,xunit.net,asp.net-core-webapi,.net Core,Visual Studio 2017,Xunit.net,Asp.net Core Webapi,我有一个比一般复杂(我怀疑)的解决方案,在升级到dotnet sdk 1.1和Visual Studio 2017后,我在从命令行构建和测试该解决方案时遇到了困难 它一直在VS2015中使用dotnet sdk 1.0.0-preview2-003131,因此它可以在VS2015和buildserver上的命令行中构建和运行 但升级到VS 2017后,我遇到了一些问题 以概述设置。 我有一个大致如下的解决方案(现实生活中的更多项目) MySolution.sln FoundationClass

我有一个比一般复杂(我怀疑)的解决方案,在升级到dotnet sdk 1.1和Visual Studio 2017后,我在从命令行构建和测试该解决方案时遇到了困难

它一直在VS2015中使用dotnet sdk 1.0.0-preview2-003131,因此它可以在VS2015和buildserver上的命令行中构建和运行

但升级到VS 2017后,我遇到了一些问题

以概述设置。 我有一个大致如下的解决方案(现实生活中的更多项目)

MySolution.sln

  • FoundationClasses(x86、.Net Framework 4.5、csproj(旧版)
  • BusinessLogic(x86,.Net Framework 4.5,csproj(立法会)
      引用基础类
  • WebApi(Dotnet核心WebApi、net451、x86(运行时)(win8-x86、win10-x86)
  • 测试项目(dotnetcore、net451x86)
    • 参考WebApi
在VS 2015中,通过将restore.dg和project.fragment.lock.json存储在Git中,我可以运行dotnet restore,然后运行dotnet build和dotnet test,从而实现这一点

升级到VS 2017之后,当我从VisualStudio构建和运行时,一切都很好。(迁移有一些关于基础项目引用的问题,但是删除了那些,在迁移之后读取,然后一切都好了)

“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测试资源管理器中很好地运行测试。Unittests运行良好并且是绿色的。但是我启动TestServer的集成测试失败,引用不匹配Microsoft.Extensions.DependencyInjection.Abstracts 1.0.0和1.1.0

因此,测试链中的某些内容需要1.0.0的程序集,但在debug dir中只能找到1.1.0

这可以通过程序集重定向来解决,但相当多的程序集似乎是错误的/不匹配的

如果我运行'dotnettest--no buildtestproject/TestProject.csproj',测试都是绿色的,而且没有问题

悬而未决的问题:

  • “dotnet msbuild”是构建混合解决方案的正确方法吗
  • 如果我在没有--no build的情况下运行“dotnet test”,则编译失败,错误与“dotnet build”(不是msbuild)类似
  • 基于我的测试中的不一致性是什么?我如何在VS中执行与从CLI相同的不一致性(最好弄清楚VS 2017中需要1.0.0范围内的程序集的内容)
我希望我能解释得很透彻(但又足够简单易懂)

如果需要更多信息来理解该场景,请让我知道

致意
安德斯

好吧,经过几个小时的深思熟虑,我想我找到了正确的解决办法

我将在这里发布以供参考

交叉引用dotnet cli问题:

我有一个构建到.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文件夹的程序集。而这些程序集并不相同

因此,要像VisualStudio一样构建,我必须找到要使用的正确msbuild可执行文件

VisualStudio团队已经为我在构建脚本中使用的()开发了一个工具

有了它,一切都会运转起来

下面是我构建和测试解决方案的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()

告诉XUnit不要进行卷影复制,这样OpenCover就可以找到与测试中的可执行文件匹配的PDB文件

最后

在Visual Studio中运行测试时,所有使用Microsoft.AspNetCore.TestHost.TestServer引用某些dotnet核心程序集的测试都失败,因为“某物”引用了程序集的V1.0.0版本,而我的项目引用了V1.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>

"
呸……那是一场激烈的战斗

但不管它值多少钱

在全新的.net核心Web Api解决方案中运行的一个结合了传统x86、net 4,5程序集的组合解决方案可以工作-我很高兴..-)

<?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>