将测试项目appSettings附加到ASP.NET Core集成测试

Jer*_*oen 3 c# integration-testing xunit asp.net-core

我将在这些文档之后创建ASP.NET Core集成测试(基于xUnit)。我想用它自己的启动测试Web服务器appsettings.json。我的缩写文件夹结构是:

\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
Run Code Online (Sandbox Code Playgroud)

然后我有这些实用程序:

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>();
    }
}
Run Code Online (Sandbox Code Playgroud)

在内部,Startup.cs ConfigureServices(...)我这样做:

services.AddOptions<SystemOptions>(Configuration.GetSection("System"));
Run Code Online (Sandbox Code Playgroud)

appsettings.json像这样引用该部分:

"System": {
  "PingMessageSuffix": " suffix-from-actual-project"
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好:这是通过强类型化方式获得的。我的控制器获得了一个SystemOptions反映json结构的实例,并且控制器正确使用了后缀。

问题在于构建集成测试WebHost。我想Startup使用自己的appsettings.json设置按原样运行真实项目,但是作为额外的一层设置,我希望添加appsettings.json 测试csproj中的设置,并覆盖所有适用的设置。这是我来自测试项目的设置:

"System": {
  "PingMessageSuffix": " suffix-from-test-appsettings"
}
Run Code Online (Sandbox Code Playgroud)

这是我尝试过的:

public class CustomWebApplicationFactory : WebApplicationFactory<Startup>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder
            .UseStartup<Startup>()
            .ConfigureAppConfiguration(config => config
                .AddJsonFile("appsettings.json")
            );
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用。如果我在控制器中遇到断点,我只会看到基础项目中的设置。控制器仅回显当前的config值,并且逻辑上返回结果也不符合预期。

该文档在页面上的任何地方都没有提及“设置”。

底线:运行ASP.NET Core集成测试时,如何从测试项目的appsettings.json文件中添加一层appSettings?

Jer*_*oen 5

像这样解决它:

  1. 对于appsettings.json在测试项目中设置的属性:
    • Build ActionContent
    • Copy to Output DirectoryCopy if newer
  2. 使用这样的自定义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"))
            );
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

瞧,它有效!

需要第一步,以便轻松ConfigurationBuilder找到您的json文件。第二步巧妙地使用了一个...TestServices配置(如果您使用常规ConfigureServices方法,它将在启动服务配置之前被调用并被覆盖)。

脚注:评论员(关于这个问题)已经提到,最好appsettings.ci.json在SUT项目中有一个文件,并按环境(您可以通过启动设置或WebHostBuilder进行设置)控制事物。文档链接到建议同一件事的几个封闭的GitHub的问题:871290607153。根据您的情况和口味,这可能是更好或更惯用的解决方案。

  • 天哪-那些向下箭头很棒!(是的,我知道...这是小事...) (2认同)

Dal*_*oft 5

\n

2020 年 2 月更新 - ASP.NET Core 3.0 及更高版本

\n
\n\n

执行此操作的方式已更改,您需要使用ConfigureAppConfiguration 委托。

\n\n
public class HomeControllerTests : IClassFixture<WebApplicationFactory<Startup>>\n{\n    private readonly WebApplicationFactory<Startup> _factory;\n\n    public HomeControllerTests(WebApplicationFactory<Startup> factory)\n    {\n        var projectDir = Directory.GetCurrentDirectory();\n        var configPath = Path.Combine(projectDir, "appsettings.json");\n\n         //New              \xe2\x86\x93\xe2\x86\x93\xe2\x86\x93              \n        _factory = factory.WithWebHostBuilder(builder =>\n        {\n            builder.ConfigureAppConfiguration((context,conf) =>\n            {\n                conf.AddJsonFile(configPath);\n            });\n\n        });\n     }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

致谢: https: //gunnarpeipman.com/aspnet-core-integration-tests-appsettings/

\n