Net Core 集成测试:运行 Startup.cs 和来自其他程序的配置

Net Core Integration Test: Run Startup.cs and Configuration from other Program

我们正在创建一个集成单元测试 (Xunit),它正在调用真实应用程序 Startup.cs。

出于某种原因,真实项目可以正确读取配置 file/property,但是 运行 它无法从集成测试中读取。它没有将任何内容放入下面的 Configuration (conf) 变量中。我将如何解决这个问题? 原因是它没有接受是因为它没有读取 Net Core 2.2 中新的内部依赖注入,它读取配置文件。现在正在尝试使用 .CreateDefaultBuilder。

IntegrationTest1.cs

        TestServer _server = new TestServer(new WebHostBuilder() .UseContentRoot("C:\RealProject\RealProject.WebAPI")
            .UseEnvironment("Development")
            .UseConfiguration(new ConfigurationBuilder()
            .SetBasePath("C:\RealProject\RealProject.WebAPI")
                .AddJsonFile("appsettings.json")
                .Build())
                .UseStartup<Startup>()
            .UseStartup<Startup>());

真实项目Startup.cs

    public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment)
    {
        Configuration = configuration;
        HostingEnvironment = hostingEnvironment;
    }

    public IHostingEnvironment HostingEnvironment { get; }
    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {

        var conf = Configuration;
        IConfiguration appConf = conf.GetSection("ConnectionStrings");
        var connstring = appConf.GetValue<string>("DatabaseConnection");

        services.AddDbContext<DbContext>(a => a.UseSqlServer(connstring));

Appsettings.Json

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "ConnectionStrings": {
    "DatabaseConnection": "Data Source=.;Initial Catalog=ApplicationDatabase;Integrated Security=True"
  }
}

您要做的是为您的 WebApplication 创建一个采用 Startup 类型的工厂。然后,您可以使用 IClassFixture 接口与测试 class.

中的所有测试共享此工厂的上下文

实际情况是这样的:

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup> where TStartup : class
{
    public CustomWebApplicationFactory() { }

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder
            .ConfigureTestServices(
                services =>
                {
                    services.Configure(AzureADDefaults.OpenIdScheme, (System.Action<OpenIdConnectOptions>)(o =>
                    {
                        // CookieContainer doesn't allow cookies from other paths
                        o.CorrelationCookie.Path = "/";
                        o.NonceCookie.Path = "/";
                    }));
                }
            )
            .UseEnvironment("Production")
            .UseStartup<Startup>();
    }
}


public class AuthenticationTests : IClassFixture<CustomWebApplicationFactory<Startup>>
{
    private HttpClient _httpClient { get; }

    public AuthenticationTests(CustomWebApplicationFactory<Startup> fixture)
    {
        WebApplicationFactoryClientOptions webAppFactoryClientOptions = new WebApplicationFactoryClientOptions
        {
            // Disallow redirect so that we can check the following: Status code is redirect and redirect url is login url
            // As per https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2#test-a-secure-endpoint
            AllowAutoRedirect = false
        };

        _httpClient = fixture.CreateClient(webAppFactoryClientOptions);
    }

    [Theory]
    [InlineData("/")]
    [InlineData("/Index")]
    [InlineData("/Error")]
    public async Task Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(string url)
    {
        // Act
        HttpResponseMessage response = await _httpClient.GetAsync(url);

        // Assert
        response.EnsureSuccessStatusCode();
    }
}

我按照指南 here 在我自己的代码中实现了这一点。