Тест интеграции ядра Net: запустите Startup.cs и конфигурацию из другой программы

Мы создаем тест Integration Unit (Xunit), который вызывает Real Application Startup.cs.

По какой-то причине настоящий проект может правильно читать файл / свойство конфигурации, однако, запустив его из теста интеграции, он не может его прочитать. Он ничего не помещает в переменную 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>());

Real Project 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"
  }
}

person Community    schedule 01.08.2019    source источник


Ответы (1)


Что вы хотите сделать, так это создать Factory для вашего WebApplication, который принимает тип запуска. Затем вы можете использовать интерфейс IClassFixture, чтобы поделиться контекстом этой фабрики со всеми ваших тестов в вашем тестовом классе.

Как это выглядит на практике:

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();
    }
}

Чтобы заставить это работать в моем собственном коде.

person Matt Stannett    schedule 02.08.2019
comment
пытаясь реализовать больше этого стиля ответа, от Джона Дж. stackoverflow.com/questions/41382978/ - person ; 02.08.2019
comment
есть ли способ упростить и использовать это? var projectDir = System.IO.Directory.GetCurrentDirectory (); _server = new TestServer (новый WebHostBuilder () .UseEnvironment (Development) .UseContentRoot (projectDir) .UseConfiguration (new ConfigurationBuilder () .SetBasePath (projectDir) .AddJsonFile (appsettings.json) .Build ()) ‹UseStartup. ); stackoverflow .com / questions / 41382978 / - person ; 02.08.2019
comment
Я обновил свой ответ, я использую метод, позволяющий найти projectDir. - person John_J; 05.08.2019
comment
привет @MattStannett, можете ли вы использовать конфигурацию установки в соответствии с фактическим каталогом вопросов, спасибо? Я мог бы послать награду за вопрос позже, ответ не работал новый TestServer (новый WebHostBuilder () .UseContentRoot (C: \\ RealProject \\ RealProject.WebAPI) .UseEnvironment (Development) .UseConfiguration (new ConfigurationBuilder () .SetBasePath (C: \\ RealProject \\ RealProject.WebAPI) .AddJsonFile (appsettings.json) .Build ()) .UseStartup ‹Startup› () .UseStartup ‹Startup› ()); - person ; 06.08.2019
comment
здесь более подробный вопрос, на который нужно ответить с полными спецификациями, у команды возникла проблема с отладкой / настройкой stackoverflow.com/questions/57331395/ Мохсен Эсмаилпур говорил только о веб-фабрике - person ; 06.08.2019
comment
Вы использовали Startup вместо TStartup в двух строках. Это ошибка? - person Massimiliano Kraus; 01.05.2020
comment
Нет, это соглашение для дженериков - где их тип указывается при создании. - person Matt Stannett; 01.05.2020