简体   繁体   中英

C# Environment variables in integration test

I have built a custom web application Factory to run a in memory test server for integration tests. Instead of using in memory database, we are trying to use a sql database.

My problem is that the connection string is changing for each environment. We have several appsettings{envName}.json files with the connection string. So, I need to find a solution for getting the env variable. These are my tries:

public class CustomWebApplicationSQLServerFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureServices(services =>
        {
            var serviceProvider = new ServiceCollection()
                .AddEntityFrameworkSqlServer()
                .BuildServiceProvider();

            var env = serviceProvider.GetService<IHostingEnvironment>();

            Configuration = new ConfigurationBuilder()
                .SetBasePath(AppContext.BaseDirectory)
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables()
                .Build();

            var defaultConnection = Configuration.GetConnectionString("DefaultConnection");
            var connectionString = string.Format(defaultConnection, "TestSampleOrder_" + Guid.NewGuid().ToString());

            services.AddDbContext<SampleOrderContext>(options =>
            {
                options.UseSqlServer(connectionString);
                options.UseInternalServiceProvider(serviceProvider);
            });

            var sp = services.BuildServiceProvider();

            using (var scope = sp.CreateScope())
            {
                var scopedServices = scope.ServiceProvider;

                var context = scopedServices.GetRequiredService<SampleOrderContext>();

                DbInitializer.InitializeDbForTests(context);
            }
        });
    }

Also I have added in my test Project a launchSettings.json file. In that file, under my test Project name, I have added "ASPNETCORE_ENVIRONMENT": "AnyValue". So, I can't understand why env = null . After doing more tests, env.EnvironmentName = "Development", and application name and path are the main Project. Why? "Development" Word is NOT set in the hole solution.

I tried also replace the env line for this one:

var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

If I set a Windows variable, I can get the value using that, but I need to understand how can I set the value of the variable in my launchSettings file.

Another thing I have tried is this:

var serviceProvider = services.BuildServiceProvider();

But I really don't understand the difference.

Can anyone please help me to understand how this is working, what is the best way to get the env variable and what is the difference between using services.BuildServiceProvider() and new ServiceCollection()?

Thanks a lot.

Perhaps this question could provide some insight.

That being said, the "simplest" way to go about testing with configuration is to abstract what you need. Maybe you could build an adapter that gives you the environment name, eg:

public interface IApplicationConfiguration
{
    string GetEnvironmentName();
}

public class ApplicationConfiguration
{
    private IHostingEnvironment _hostingConfiguration;

    public ApplicationConfiguration(IHostingEnvironment hostingConfiguration)
    {
        _hostingConfiguration = hostingConfiguration;
    }

    public string GetEnvironmentName()
    {
        return _hostingConfiguration.EnvironmentName;
    }
}

You could solve it using other options but mocking these type of settings can be quite useful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM