我正在these docs之后创建ASP.NET Core集成测试(基于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"
}
到目前为止非常好:这是通过强类型化方式实现的。我的控制器获得了一个反映json结构的SystemOptions
实例,并且控制器正确使用了后缀。 / p>
问题在于构建Integration Tests WebHost 。我想从真实项目中直接运行Startup
,并使用其自己的appsettings.json
设置,但是作为额外的设置层,我希望从测试csproj中的appsettings.json
< / em>添加,覆盖所有设置(如果适用)。这是我在测试项目中的设置:
"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")
);
}
}
但是,这不起作用。如果我在控制器中遇到断点,我只会看到基础项目中的设置。控制器仅回显当前的config值,逻辑上返回结果也不符合预期。
The documentation在页面上的任何地方都没有提及“设置”。
底线:运行ASP.NET Core集成测试时,如何从测试项目的appsettings.json文件中添加一层appSettings?
答案 0 :(得分:4)
像这样解决它:
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
方法,则在启动服务配置之前将其称为 并被覆盖)。
脚注:评论者(在问题上)提到,在SUT项目中有一个appsettings.ci.json
文件并按环境控制内容(您可以通过以下方法进行设置)可能会更好启动设置或通过WebHostBuilder)。该文档链接到一些封闭的GitHub问题,这些问题暗示着同样的事情:8712,9060,7153。根据您的情况和口味,这可能是更好或更惯用的解决方案。
答案 1 :(得分:3)
更新2020年2月-ASP.NET Core 3.0及更高版本
更改方式,您需要使用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/
答案 2 :(得分:0)
单元测试项目和集成测试项目都将需要自己的应用程序设置。我们称其为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文件。