将测试项目 appSettings 附加到 ASP.NET 核心集成测试
Append test project appSettings to ASP.NET Core integration tests
我正在 these docs 之后创建 ASP.NET 核心集成测试(基于 xUnit)。我想用自己的 appsettings.json
启动测试 Web 服务器。我的缩写文件夹结构是:
\SampleAspNetWithEfCore
\SampleAspNetWithEfCore\SampleAspNetWithEfCore.csproj
\SampleAspNetWithEfCore\Startup.cs
\SampleAspNetWithEfCore\appsettings.json
\SampleAspNetWithEfCore\Controllers\*
\SampleAspNetWithEfCore.Tests\SampleAspNetWithEfCore.Tests.csproj
\SampleAspNetWithEfCore.Tests\IntegrationTests.cs
\SampleAspNetWithEfCore.Tests\appsettings.json
然后我有这些实用程序:
public static class ServicesExtensions
{
public static T AddOptions<T>(this IServiceCollection services, IConfigurationSection section)
where T : class, new()
{
services.Configure<T>(section);
services.AddSingleton(provider => provider.GetRequiredService<IOptions<T>>().Value);
return section.Get<T>();
}
}
在 Startup.cs
ConfigureServices(...)
里面 我这样做:
services.AddOptions<SystemOptions>(Configuration.GetSection("System"));
引用 appsettings.json
部分是这样的:
"System": {
"PingMessageSuffix": " suffix-from-actual-project"
}
到目前为止一切顺利:这是以强类型方式获取的。我的控制器得到一个 SystemOptions
实例,它反映了 json 结构,控制器正确使用后缀。
问题在于构建集成测试 WebHost。我想 运行 我的真实项目中的 Startup
有自己的 appsettings.json
设置,但作为额外的一层设置,我想要 appsettings.json
从我的测试 csproj 添加,覆盖任何设置(如果适用)。这是我在测试项目中的应用程序设置:
"System": {
"PingMessageSuffix": " suffix-from-test-appsettings"
}
这是我试过的方法:
public class CustomWebApplicationFactory : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder
.UseStartup<Startup>()
.ConfigureAppConfiguration(config => config
.AddJsonFile("appsettings.json")
);
}
}
但是,这不起作用。如果我在控制器中遇到断点,我只会看到基础项目的设置。控制器只是回显当前的配置值,逻辑上 return 结果也不符合预期。
The documentation 没有在页面的任何地方提到 "appsettings"。
底线:当 运行ning ASP.NET 核心集成时,如何从测试项目的 appsettings.json 文件中添加一层 appSettings测试?
单元测试项目和集成测试项目都需要自己的应用程序设置。我们称我们的 appsettings.Test.json
然后我们使用Microsoft.Extensions.Configuration来访问它们。所以通常在测试中我会做类似的事情:
private readonly IConfiguration _configuration;
public HomeControllerTests()
{
_configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.Test.json")
.Build();
}
然后通过以下方式引用此文件中的值:
_configuration["user:emailAddress"]
文件看起来像:
"user": { "emailAddress": "myemail.com", …...
对于您正在尝试做的事情,您可能需要创建一个类似于我的 appsettings.test.json 文件,该文件位于您的主 apsettings 文件旁边。然后您需要测试环境,然后添加适当的应用程序设置文件。
这样解决的:
- 对于
appsettings.json
在测试项目中设置属性:
Build Action
到 Content
Copy to Output Directory
到 Copy if newer
像这样使用自定义 WebApplicationFactory
:
public class CustomWebApplicationFactory : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
// Note: ↓↓↓↓
builder.ConfigureTestServices(services =>
services.AddOptions<SystemOptions>(configuration.GetSection("System"))
);
}
}
瞧:它有效!
第一步是让 ConfigurationBuilder
轻松找到您的 json 文件。第二步巧妙地使用了 ...TestServices
配置(如果你使用常规的 ConfigureServices
方法,它将在 之前被调用 Startup 的服务配置并被覆盖)。
脚注:评论者(关于这个问题)提到在 SUT 项目中有一个 appsettings.ci.json
文件可能更好,并通过环境控制事物(这您将通过启动设置或通过 WebHostBuilder 进行设置)。该文档链接到一些已关闭的 GitHub 问题,这些问题表明同样的事情:8712, 9060, 7153。根据您的情况和品味,这可能是更好或更惯用的解决方案。
Update Feb 2020 - ASP.NET Core 3.0 and above
您执行此操作的方式已更改,您需要使用 ConfigureAppConfiguration 委托。
public class HomeControllerTests : IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public HomeControllerTests(WebApplicationFactory<Startup> factory)
{
var projectDir = Directory.GetCurrentDirectory();
var configPath = Path.Combine(projectDir, "appsettings.json");
//New ↓↓↓
_factory = factory.WithWebHostBuilder(builder =>
{
builder.ConfigureAppConfiguration((context,conf) =>
{
conf.AddJsonFile(configPath);
});
});
}
}
归功于:https://gunnarpeipman.com/aspnet-core-integration-tests-appsettings/
我正在 these docs 之后创建 ASP.NET 核心集成测试(基于 xUnit)。我想用自己的 appsettings.json
启动测试 Web 服务器。我的缩写文件夹结构是:
\SampleAspNetWithEfCore
\SampleAspNetWithEfCore\SampleAspNetWithEfCore.csproj
\SampleAspNetWithEfCore\Startup.cs
\SampleAspNetWithEfCore\appsettings.json
\SampleAspNetWithEfCore\Controllers\*
\SampleAspNetWithEfCore.Tests\SampleAspNetWithEfCore.Tests.csproj
\SampleAspNetWithEfCore.Tests\IntegrationTests.cs
\SampleAspNetWithEfCore.Tests\appsettings.json
然后我有这些实用程序:
public static class ServicesExtensions
{
public static T AddOptions<T>(this IServiceCollection services, IConfigurationSection section)
where T : class, new()
{
services.Configure<T>(section);
services.AddSingleton(provider => provider.GetRequiredService<IOptions<T>>().Value);
return section.Get<T>();
}
}
在 Startup.cs
ConfigureServices(...)
里面 我这样做:
services.AddOptions<SystemOptions>(Configuration.GetSection("System"));
引用 appsettings.json
部分是这样的:
"System": {
"PingMessageSuffix": " suffix-from-actual-project"
}
到目前为止一切顺利:这是以强类型方式获取的。我的控制器得到一个 SystemOptions
实例,它反映了 json 结构,控制器正确使用后缀。
问题在于构建集成测试 WebHost。我想 运行 我的真实项目中的 Startup
有自己的 appsettings.json
设置,但作为额外的一层设置,我想要 appsettings.json
从我的测试 csproj 添加,覆盖任何设置(如果适用)。这是我在测试项目中的应用程序设置:
"System": {
"PingMessageSuffix": " suffix-from-test-appsettings"
}
这是我试过的方法:
public class CustomWebApplicationFactory : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder
.UseStartup<Startup>()
.ConfigureAppConfiguration(config => config
.AddJsonFile("appsettings.json")
);
}
}
但是,这不起作用。如果我在控制器中遇到断点,我只会看到基础项目的设置。控制器只是回显当前的配置值,逻辑上 return 结果也不符合预期。
The documentation 没有在页面的任何地方提到 "appsettings"。
底线:当 运行ning ASP.NET 核心集成时,如何从测试项目的 appsettings.json 文件中添加一层 appSettings测试?
单元测试项目和集成测试项目都需要自己的应用程序设置。我们称我们的 appsettings.Test.json
然后我们使用Microsoft.Extensions.Configuration来访问它们。所以通常在测试中我会做类似的事情:
private readonly IConfiguration _configuration;
public HomeControllerTests()
{
_configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.Test.json")
.Build();
}
然后通过以下方式引用此文件中的值:
_configuration["user:emailAddress"]
文件看起来像:
"user": { "emailAddress": "myemail.com", …...
对于您正在尝试做的事情,您可能需要创建一个类似于我的 appsettings.test.json 文件,该文件位于您的主 apsettings 文件旁边。然后您需要测试环境,然后添加适当的应用程序设置文件。
这样解决的:
- 对于
appsettings.json
在测试项目中设置属性:Build Action
到Content
Copy to Output Directory
到Copy if newer
像这样使用自定义
WebApplicationFactory
:public class CustomWebApplicationFactory : WebApplicationFactory<Startup> { protected override void ConfigureWebHost(IWebHostBuilder builder) { var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .Build(); // Note: ↓↓↓↓ builder.ConfigureTestServices(services => services.AddOptions<SystemOptions>(configuration.GetSection("System")) ); } }
瞧:它有效!
第一步是让 ConfigurationBuilder
轻松找到您的 json 文件。第二步巧妙地使用了 ...TestServices
配置(如果你使用常规的 ConfigureServices
方法,它将在 之前被调用 Startup 的服务配置并被覆盖)。
脚注:评论者(关于这个问题)提到在 SUT 项目中有一个 appsettings.ci.json
文件可能更好,并通过环境控制事物(这您将通过启动设置或通过 WebHostBuilder 进行设置)。该文档链接到一些已关闭的 GitHub 问题,这些问题表明同样的事情:8712, 9060, 7153。根据您的情况和品味,这可能是更好或更惯用的解决方案。
Update Feb 2020 - ASP.NET Core 3.0 and above
您执行此操作的方式已更改,您需要使用 ConfigureAppConfiguration 委托。
public class HomeControllerTests : IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public HomeControllerTests(WebApplicationFactory<Startup> factory)
{
var projectDir = Directory.GetCurrentDirectory();
var configPath = Path.Combine(projectDir, "appsettings.json");
//New ↓↓↓
_factory = factory.WithWebHostBuilder(builder =>
{
builder.ConfigureAppConfiguration((context,conf) =>
{
conf.AddJsonFile(configPath);
});
});
}
}
归功于:https://gunnarpeipman.com/aspnet-core-integration-tests-appsettings/