I have an integration tests project that uses .UseSetting()
in the test class, as follows:
我有一个集成测试项目,在测试类中使用.UseSetting(),如下所示:
public AccessTokenRetrieval() : base(nameof(AccessTokenRetrieval))
{
var connectionString = GetConnectionString();
var dbSettings = new DbSettings(connectionString);
_userGroupRepository = new UserGroupRepository(dbSettings);
_roleRepository = new RoleRepository(dbSettings);
_userRepository = new UserRepository(dbSettings);
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>()
.UseEnvironment("IntegrationTest")
.UseSetting("IntegrationTestConnString", dbSettings.IdentityServerConnectionString));
_handler = _server.CreateHandler();
_client = _server.CreateClient();
}
I would now like to retrieve that setting in the Startup.cs of my actual project. I attempted to do so using:
现在我想在启动时检索该设置。实际项目的cs。我试图这样做:
public void ConfigureIntegrationTestServices(IServiceCollection services)
{
var connectionString = Configuration.GetValue<string>("IntegrationTestConnString");
BuildIdentityServerTests(services, connectionString);
AddCoreServices(services, connectionString);
}
but that seems to return null.
但这似乎返回了null。
What is the proper way to retrieve this setting?
检索此设置的正确方法是什么?
2 个解决方案
#1
2
Per-test setting
To pass a setting into a particular TestHost
instance, you could use ConfigureServices
call and override default setting registration.
要将设置传递到特定的TestHost实例,可以使用ConfigureServices调用并覆盖默认设置注册。
First of all, register your default DbSettings
instance in Startup.ConfigureServices
method. It's mandatory to use TryAll
call:
首先,在Startup中注册默认的DbSettings实例。ConfigureServices方法。必须使用TryAll call:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton(new DbSettings(...));
}
}
Register a mocked instance in WebHostBuilder.ConfigureServices
call:
在WebHostBuilder中注册一个模拟实例。ConfigureServices电话:
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>()
.ConfigureServices(services =>
{
services.AddSingleton(new DbSettings(...));
}
);
When you try to resolve a DbSettings
in the application code, you will get a mocked instance. Because WebHostBuilder.ConfigureServices
is executed first and TryAdd
call prevents to register a default instance.
当您尝试在应用程序代码中解析DbSettings时,您将得到一个模拟的实例。因为WebHostBuilder。首先执行ConfigureServices, TryAdd调用将阻止注册一个默认实例。
This hint allows to replace any DI dependency you registered.
这个提示允许替换您注册的任何DI依赖项。
Global setting
To set an invariant (accross all tests) setting, set an process-scoped environment variable instead of UseSetting
call:
要设置不变量(包括所有测试)设置,请设置流程范围内的环境变量,而不是usestting调用:
Environment.SetEnvironmentVariable("foo", "bar");
var _server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>()
);
Then read it:
然后读:
public void ConfigureServices(IServiceCollection services)
{
string setting1 = Configuration["foo"];
string setting2 = Environment.GetEnvironmentVariable("foo");
}
You need to add environment variable provider to read variables from Configuration
:
您需要添加环境变量提供程序来从配置中读取变量:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
//this config provider is mandatory to read env vars from Configuration
.AddEnvironmentVariables();
Configuration = builder.Build();
}
#2
1
You could just inject the IConfigurationRoot where you could just use a local config file in the test project. You'd lose the default environment-specific config overrides that are the default in the new project template, but I personally don't use those for configuration management anyway (preferring non-committed appsetting.local.json instead which can be unique to developers and to the CI server).
您只需注入icon具象根,在那里您可以在测试项目中使用本地配置文件。您将丢失新项目模板中默认的特定于环境的默认配置重写,但我个人不会将它们用于配置管理(更喜欢不提交的appsett.net .local)。而json可以是开发人员和CI服务器独有的)。
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile("appsettings.local.json", optional: true, reloadOnChange: true)
.AddInMemoryCollection(new Dictionary<string, string>
{
{"myConfig:setting1", "value1"},
{"myConfig:setting2", "value2"}
})
.Build();
var server = new TestServer(new WebHostBuilder()
.UseUrls("http://localhost:5001")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.ConfigureServices(services => services.AddSingleton(configuration)));
And for Startup:
和启动:
public class Startup
{
public Startup(IConfigurationRoot configuration)
{
this.Configuration = configuration;
}
...
}
Edit: While this does work, it also seems to break IOptionsSnapshot
configuration injections from recognizing config file changes at run-time. I'm going to leave this answer, but will also keep digging for better way without injecting a custom service just to support test/fixture-specific config overrides.
编辑:虽然这是可行的,但它似乎也会在运行时从识别配置文件更改中中断IOptionsSnapshot配置。我将留下这个答案,但也将继续挖掘更好的方法,而不注入自定义服务来支持特定于测试/修复的配置重写。
#1
2
Per-test setting
To pass a setting into a particular TestHost
instance, you could use ConfigureServices
call and override default setting registration.
要将设置传递到特定的TestHost实例,可以使用ConfigureServices调用并覆盖默认设置注册。
First of all, register your default DbSettings
instance in Startup.ConfigureServices
method. It's mandatory to use TryAll
call:
首先,在Startup中注册默认的DbSettings实例。ConfigureServices方法。必须使用TryAll call:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton(new DbSettings(...));
}
}
Register a mocked instance in WebHostBuilder.ConfigureServices
call:
在WebHostBuilder中注册一个模拟实例。ConfigureServices电话:
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>()
.ConfigureServices(services =>
{
services.AddSingleton(new DbSettings(...));
}
);
When you try to resolve a DbSettings
in the application code, you will get a mocked instance. Because WebHostBuilder.ConfigureServices
is executed first and TryAdd
call prevents to register a default instance.
当您尝试在应用程序代码中解析DbSettings时,您将得到一个模拟的实例。因为WebHostBuilder。首先执行ConfigureServices, TryAdd调用将阻止注册一个默认实例。
This hint allows to replace any DI dependency you registered.
这个提示允许替换您注册的任何DI依赖项。
Global setting
To set an invariant (accross all tests) setting, set an process-scoped environment variable instead of UseSetting
call:
要设置不变量(包括所有测试)设置,请设置流程范围内的环境变量,而不是usestting调用:
Environment.SetEnvironmentVariable("foo", "bar");
var _server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>()
);
Then read it:
然后读:
public void ConfigureServices(IServiceCollection services)
{
string setting1 = Configuration["foo"];
string setting2 = Environment.GetEnvironmentVariable("foo");
}
You need to add environment variable provider to read variables from Configuration
:
您需要添加环境变量提供程序来从配置中读取变量:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
//this config provider is mandatory to read env vars from Configuration
.AddEnvironmentVariables();
Configuration = builder.Build();
}
#2
1
You could just inject the IConfigurationRoot where you could just use a local config file in the test project. You'd lose the default environment-specific config overrides that are the default in the new project template, but I personally don't use those for configuration management anyway (preferring non-committed appsetting.local.json instead which can be unique to developers and to the CI server).
您只需注入icon具象根,在那里您可以在测试项目中使用本地配置文件。您将丢失新项目模板中默认的特定于环境的默认配置重写,但我个人不会将它们用于配置管理(更喜欢不提交的appsett.net .local)。而json可以是开发人员和CI服务器独有的)。
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile("appsettings.local.json", optional: true, reloadOnChange: true)
.AddInMemoryCollection(new Dictionary<string, string>
{
{"myConfig:setting1", "value1"},
{"myConfig:setting2", "value2"}
})
.Build();
var server = new TestServer(new WebHostBuilder()
.UseUrls("http://localhost:5001")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.ConfigureServices(services => services.AddSingleton(configuration)));
And for Startup:
和启动:
public class Startup
{
public Startup(IConfigurationRoot configuration)
{
this.Configuration = configuration;
}
...
}
Edit: While this does work, it also seems to break IOptionsSnapshot
configuration injections from recognizing config file changes at run-time. I'm going to leave this answer, but will also keep digging for better way without injecting a custom service just to support test/fixture-specific config overrides.
编辑:虽然这是可行的,但它似乎也会在运行时从识别配置文件更改中中断IOptionsSnapshot配置。我将留下这个答案,但也将继续挖掘更好的方法,而不注入自定义服务来支持特定于测试/修复的配置重写。