首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WebApplicationFactory - InvalidOperationException:在从Docker进行测试时,无法使用应用程序根定位解决方案根

WebApplicationFactory - InvalidOperationException:在从Docker进行测试时,无法使用应用程序根定位解决方案根
EN

Stack Overflow用户
提问于 2020-11-07 14:40:40
回答 1查看 1.2K关注 0票数 1

我正在学习ASP.NET核心,并使用ConfigureWebHost方法对WebApplicationFactory类进行子类化,如下面的清单所示。我还创建了一个小型GitHub存储库来突出我遇到的问题。

代码语言:javascript
运行
复制
/// <summary>
/// Set the content root to path relative to sln, e.g. Src/WebApp
/// Configure the webhost using appsettings.json from the path where the assembly is located for 
/// the startup class. The Autofac container is configured here also.
/// </summary>
/// <seealso cref="Microsoft.AspNetCore.Mvc.Testing.ConfigureWebHost(IWebHostBuilder)"/></seealso>
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
    string path = Assembly.GetAssembly(typeof(WebApiTestFactory<TStartupClass>)).Location;

    builder.UseSolutionRelativeContentRoot(_contentRoot)
        .ConfigureAppConfiguration(cb =>
        {
            cb.AddJsonFile($"{Path.GetDirectoryName(path)}/appsettings.json", optional: false)
                .AddEnvironmentVariables();
        })
        .ConfigureServices(services => services.AddAutofac());

    base.ConfigureWebHost(builder);
}

这使用UseSolutionRelativeContentRoot设置相对于包含*.sln文件的目录的内容根路径。

我的集成测试在本地开发环境中成功运行。

但是,当我在码头容器中运行测试时,会引发InvalidOperationExceptionSolution root could not be located using application root

我有什么办法解决这个问题吗?

异常

代码语言:javascript
运行
复制
A total of 1 test files matched the specified pattern.
/Tests/FunctionalTests/WebApp.FunctionalTests/bin/Debug/netcoreapp3.1/WebApp.FunctionalTests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit .NET Core 3.1.9)
[xUnit.net 00:00:00.88]   Discovering: WebApp.FunctionalTests
[xUnit.net 00:00:00.94]   Discovered:  WebApp.FunctionalTests
[xUnit.net 00:00:00.95]   Starting:    WebApp.FunctionalTests
[xUnit.net 00:00:01.17]     WebApp.FunctionalTests.ApiTest.WebApp_ApiController_DownloadImage [FAIL]
[xUnit.net 00:00:01.17]       System.InvalidOperationException : Solution root could not be located using application root /Tests/FunctionalTests/WebApp.FunctionalTests/bin/Debug/netcoreapp3.1/.
[xUnit.net 00:00:01.18]       Stack Trace:
[xUnit.net 00:00:01.18]            at Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(IWebHostBuilder builder, String solutionRelativePath, String applicationBasePath, String solutionName)
[xUnit.net 00:00:01.18]            at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.SetContentRoot(IWebHostBuilder builder)
[xUnit.net 00:00:01.18]            at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.EnsureServer()
[xUnit.net 00:00:01.18]            at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateDefaultClient(DelegatingHandler[] handlers)
[xUnit.net 00:00:01.18]            at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateDefaultClient(Uri baseAddress, DelegatingHandler[] handlers)
[xUnit.net 00:00:01.18]            at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options)
[xUnit.net 00:00:01.18]            at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient()
[xUnit.net 00:00:01.18]         /Tests/FunctionalTests/WebApp.FunctionalTests/ApiTest.cs(45,0): at WebApp.FunctionalTests.ApiTest.WebApp_ApiController_DownloadImage()
[xUnit.net 00:00:01.18]         --- End of stack trace from previous location where exception was thrown ---
[xUnit.net 00:00:01.19]   Finished:    WebApp.FunctionalTests
  X WebApp.FunctionalTests.ApiTest.WebApp_ApiController_DownloadImage [93ms]
  Error Message:
   System.InvalidOperationException : Solution root could not be located using application root /Tests/FunctionalTests/WebApp.FunctionalTests/bin/Debug/netcoreapp3.1/.
  Stack Trace:
     at Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(IWebHostBuilder builder, String solutionRelativePath, String applicationBasePath, String solutionName)
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.SetContentRoot(IWebHostBuilder builder)
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.EnsureServer()
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateDefaultClient(DelegatingHandler[] handlers)
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateDefaultClient(Uri baseAddress, DelegatingHandler[] handlers)
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options)
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient()
   at WebApp.FunctionalTests.ApiTest.WebApp_ApiController_DownloadImage() in /Tests/FunctionalTests/WebApp.FunctionalTests/ApiTest.cs:line 45
--- End of stack trace from previous location where exception was thrown ---

Test Run Failed.
Total tests: 1
     Failed: 1
 Total time: 2.0426 Seconds
/usr/share/dotnet/sdk/3.1.403/Microsoft.TestPlatform.targets(32,5): error MSB4181: The "Microsoft.TestPlatform.Build.Tasks.VSTestTask" task returned false but did not log an error. [/Tests/FunctionalTests/WebApp.FunctionalTests/WebApp.FunctionalTests.csproj]

测试项目

代码语言:javascript
运行
复制
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>

    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <Content Update="xunit.runner.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Autofac" Version="6.0.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
    <PackageReference Include="xunit" Version="2.4.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
    <PackageReference Include="coverlet.collector" Version="1.0.1" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\..\..\Src\WebApp\WebApp.csproj" />
    <ProjectReference Include="..\..\Functional\Utilities\WebApp.Functional.Utilities.csproj" />
    <ProjectReference Include="..\..\..\Src\WebApp.S3.Contracts\WebApp.S3.Contracts.csproj" />
  </ItemGroup>

</Project>

还将Microsoft.AspNetCore.Mvc.Testing依赖项作为详细的这里添加到测试项目中,并且仍然得到相同的结果:

代码语言:javascript
运行
复制
 <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.9" />

还尝试在Test中添加WebApplicationFactoryContentRoot属性:

代码语言:javascript
运行
复制
using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

using Microsoft.AspNetCore.Hosting;
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;
using Xunit.Abstractions;

using WebApp.S3.Contracts;
using WebApp.Functional.Utilities;


/// key should match FullName assembly attributed of TStartup : WebApplicationFactory<TStartup> 
/// https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.testing.webapplicationfactorycontentrootattribute?view=aspnetcore-3.0
[assembly: WebApplicationFactoryContentRoot(
    key: "WebApp.FunctionalTests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
    contentRootPath: "../../../../../../Src/WebApp",
    contentRootTest: "Program.cs",
    priority: "1")]

namespace WebApp.FunctionalTests
{
    public class ApiTest
    {
        private TestingBase<WebAppTestStartup> _testing;
        private string _settingsFile;
        
        
        private string GetSettingsFile() 
        {
            const string AspNetCoreEnvironment="ASPNETCORE_ENVIRONMENT";
            const string DefaultSettingsFile = "appsettings.Local.json";
            
            var envVar = System.Environment.GetEnvironmentVariable(AspNetCoreEnvironment);

            if(envVar != null)
                return $"appsettings.{envVar}.json";
            else
                return DefaultSettingsFile;
        }

        /// <summary>
        /// Create Web Application Factory with content root at Src/WebApp using
        /// appsettings file derived from ASPNETCORE_ENVIRONMENT variable. If
        /// the variable is unset then defaults to appsettings.Local.json
        /// </summary>
        /// <param name="output">xUnit output stream</param>
        public ApiTest(ITestOutputHelper output)
        {
            const string contentRoot = "Src/WebApp";
            
            _settingsFile = GetSettingsFile();
            
            string startupPath = Assembly.GetAssembly(typeof(WebApiTestFactory<WebAppTestStartup>)).Location;
            string settingsFilePath = $"{Path.GetDirectoryName(startupPath)}/{_settingsFile}";

            _testing = new TestingBase<WebAppTestStartup>(output, contentRoot, settingsFilePath);
        }

        [Fact]
        public async Task WebApp_ApiController_DownloadImage()
        {
            const string TestData = "test";
            const string ObjectName = "objectName";
            byte[] Payload = Encoding.UTF8.GetBytes(TestData);

            // upload a sample image
            using (var client = _testing.Factory.CreateClient())
            using (var scope = _testing.Factory.Server.Host.Services.CreateScope())
            using (var byteStream = new MemoryStream(Payload))
            using (var stream = new BufferedStream(byteStream))
            {
                var s3Client = scope.ServiceProvider.GetRequiredService<IS3Service>();
                await s3Client.UploadAsync(stream, ObjectName);

                var response = await client.GetAsync(ApiRoutes.Get.Image(ObjectName));
                response.EnsureSuccessStatusCode();

                string result = await response.Content.ReadAsStringAsync();

                Assert.Equal(TestData, result);
            }
        }
    }
}

还尝试将其添加到csproj文件中:

代码语言:javascript
运行
复制
<Target Name="AddGitMetadaAssemblyAttributes" BeforeTargets="CoreGenerateAssemblyInfo">
    <ItemGroup>
        <AssemblyAttribute Include="Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactoryContentRoot">
            <_Parameter1>WebApp.FunctionalTests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</_Parameter1>
            <_Parameter2>../../../Src/WebApp</_Parameter2>
            <_Parameter3>appsettings.Development.json</_Parameter3>
            <_Parameter4>1</_Parameter4>
        </AssemblyAttribute>
    </ItemGroup>
  </Target>

WebApp.FunctionalTests是包含我的启动类的程序集。这是从存在于不同程序集中的活动Startup类派生的。

当有时间时,需要创建一个较小的项目并从那里进行调试。还在吉特布上提出了一项问题

EN

回答 1

Stack Overflow用户

发布于 2020-11-08 15:00:00

Microsoft.AspNetCore.Mvc.Testing已经有了一个类,用于创建TestsServers,用于使用.net核心进行集成测试,以及替换配置的方法,但不确定为什么需要创建自己的配置。我建议将您的配置添加到.net核心的DI中,并替换ConfigureServices中的配置。

我已经为这样的WebAPI编写了集成测试。您可以将它包含在每个测试类中继承的抽象类中,以满足特定需求。

代码语言:javascript
运行
复制
var appFactory = new WebApplicationFactory<Startup>()
   .WithWebHostBuilder(builder => 
      {
         builder.ConfigureServices(services => {
             // Remove/Add Services from .net CORE DI
             services.Remove(services.SingleOrDefault(
                  d => d.ServiceType == typeof(IExampleDbSettings)));
             services.AddSingleton<IExampleDbSettings>(new TestDbSettings { ... });
         }
      }

// Test HTTP Client
var httpClient = appFactory.CreateClient(); //Http Client to connect to TestServer
// Request a Token and add it to client if needed
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", "<jwt_token>");
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64728840

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档