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

时间:2018-12-10 11:09:28

标签: c# asp.net-core integration-testing xunit

我正在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?

3 个答案:

答案 0 :(得分:4)

像这样解决它:

  1. 为Test项目中的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"))
            );
        }
    }
    

瞧,这行得通!

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

脚注:评论者(在问题上)提到,在SUT项目中有一个appsettings.ci.json文件并按环境控制内容(您可以通过以下方法进行设置)可能会更好启动设置或通过WebHostBuilder)。该文档链接到一些封闭的GitHub问题,这些问题暗示着同样的事情:871290607153。根据您的情况和口味,这可能是更好或更惯用的解决方案。

答案 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文件。