我正在学习ASP.NET核心,并使用ConfigureWebHost方法对WebApplicationFactory类进行子类化,如下面的清单所示。我还创建了一个小型GitHub存储库来突出我遇到的问题。
/// <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文件的目录的内容根路径。
我的集成测试在本地开发环境中成功运行。
但是,当我在码头容器中运行测试时,会引发InvalidOperationException
:Solution root could not be located using application root
我有什么办法解决这个问题吗?
异常
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]
测试项目
<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依赖项作为详细的这里添加到测试项目中,并且仍然得到相同的结果:
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.9" />
还尝试在Test中添加WebApplicationFactoryContentRoot属性:
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文件中:
<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
类派生的。
发布于 2020-11-08 15:00:00
Microsoft.AspNetCore.Mvc.Testing
已经有了一个类,用于创建TestsServers,用于使用.net核心进行集成测试,以及替换配置的方法,但不确定为什么需要创建自己的配置。我建议将您的配置添加到.net核心的DI中,并替换ConfigureServices
中的配置。
我已经为这样的WebAPI编写了集成测试。您可以将它包含在每个测试类中继承的抽象类中,以满足特定需求。
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>");
https://stackoverflow.com/questions/64728840
复制相似问题