在 .NET Core 中使用 IOptions<> 进行集成测试
Integration test with IOptions<> in .NET Core
我将 IOption<T>
传递给 CommandBus
,这样我就可以从 ServiceBusSetting
class 中获取设置。我想对我的总线进行集成测试。我不想解决它只是使用 new QueueCommandBus
并且需要将 IOptions
传递给它。
var services = new ServiceCollection().AddOptions();
services.Configure<ServiceBusAppSettings>(Configuration.GetSection("ServiceBus"));
var options = services.BuildServiceProvider().GetService<IOptions<ServiceBusAppSettings>>();
////Act
var commandBus = new QueueCommandBus(options);
这工作正常,但在我的测试项目中从我的 appsetting.json
获取 IOptions<T>
感觉代码非常复杂。
知道这是唯一的方法还是有更好的方法?
您不需要创建 ServiceCollection
或 IServiceProvider
。 IConfiguration
接口有一个 Bind()
方法,或者从 .NET Core 1.1 开始,Get<T>
可以用来直接获取 strongly-typed 对象:
var config = Configuration.GetSection("ServiceBus");
// .NET Core 1.0
var options = new ServiceBusAppSettings();
config.Bind(options);
// .NET Core 1.1
var options = config.Get<ServiceBusAppSettings>();
我喜欢将这些作为静态方法添加到我的 AppSettings
strongly-typed 对象中,以便在我的网络应用程序和单元测试中从 JSON 加载它们很方便。
AppSettings.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
namespace My.Namespace
{
public class AppSettings
{
public class ServiceBusAppSettings
{
public string Setting1;
public int Setting2;
}
public class ApiSettings
{
public bool FormatJson { get; set; }
}
public class MySqlSettings
{
public string User { get; set; }
public string Password { get; set; }
public string Host { get; set; }
public string Database { get; set; }
public int Port { get; set; } = 3306;
public string GetConnectionString()
{
return $"Server={Host};Database={Database};Port={Port};Uid={User};Pwd={Password}";
}
}
public ServiceBusAppSettings ServiceBus { get; set; } = new ServiceBusAppSettings();
public ApiSettings Api { get; set; } = new ApiSettings();
public MySqlSettings MySql { get; set; } = new MySqlSettings();
// Static load helper methods. These could also be moved to a factory class.
public static IConfigurationRoot GetConfiguration(string dir)
{
return GetConfiguration(dir, null);
}
public static IConfigurationRoot GetConfiguration(string dir, string environmentName)
{
if (string.IsNullOrEmpty(environmentName))
environmentName = "Development";
var builder = new ConfigurationBuilder()
.SetBasePath(dir)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{environmentName}.json", true)
.AddEnvironmentVariables();
return builder.Build();
}
public static AppSettings GetSettings(string dir)
{
return GetSettings(dir, null);
}
public static AppSettings GetSettings(string dir, string environmentName)
{
var config = GetConfiguration(dir, environmentName);
return GetSettings(config);
}
public static AppSettings GetSettings(IConfiguration config)
{
return config.Get<AppSettings>();
}
}
}
ASP.NET Core Startup.cs
:(获取 strongly-typed 设置对象在配置其他服务的这个阶段通常很有帮助。 ..)
public class Startup
{
public Startup(IHostingEnvironment env)
{
Configuration = AppSettings.GetConfiguration(env.ContentRootPath, env.EnvironmentName);
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Configure the service collection.
services.AddOptions();
services.Configure<AppSettings>(Configuration);
// It can also be handy to get the AppSettings object here.
var settings = AppSettings.GetSettings(Configuration);
// Add framework services.
services.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
// Pretty-print JSON in Development
options.SerializerSettings.Formatting = settings.Api.FormatJson ? Formatting.Indented : Formatting.None;
});
// Store DB connection info in AppSettings too...
var conn = settings.MySql.GetConnectionString();
services.AddDbContext<MyDbContext>(opt => opt.UseMySql(conn));
}
}
测试中Class:
var testDir = AppContext.BaseDirectory;
var settings = AppSettings.GetSettings(testDir, "Test");
//Act
var commandBus = new QueueCommandBus(settings);
我将 IOption<T>
传递给 CommandBus
,这样我就可以从 ServiceBusSetting
class 中获取设置。我想对我的总线进行集成测试。我不想解决它只是使用 new QueueCommandBus
并且需要将 IOptions
传递给它。
var services = new ServiceCollection().AddOptions();
services.Configure<ServiceBusAppSettings>(Configuration.GetSection("ServiceBus"));
var options = services.BuildServiceProvider().GetService<IOptions<ServiceBusAppSettings>>();
////Act
var commandBus = new QueueCommandBus(options);
这工作正常,但在我的测试项目中从我的 appsetting.json
获取 IOptions<T>
感觉代码非常复杂。
知道这是唯一的方法还是有更好的方法?
您不需要创建 ServiceCollection
或 IServiceProvider
。 IConfiguration
接口有一个 Bind()
方法,或者从 .NET Core 1.1 开始,Get<T>
可以用来直接获取 strongly-typed 对象:
var config = Configuration.GetSection("ServiceBus");
// .NET Core 1.0
var options = new ServiceBusAppSettings();
config.Bind(options);
// .NET Core 1.1
var options = config.Get<ServiceBusAppSettings>();
我喜欢将这些作为静态方法添加到我的 AppSettings
strongly-typed 对象中,以便在我的网络应用程序和单元测试中从 JSON 加载它们很方便。
AppSettings.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
namespace My.Namespace
{
public class AppSettings
{
public class ServiceBusAppSettings
{
public string Setting1;
public int Setting2;
}
public class ApiSettings
{
public bool FormatJson { get; set; }
}
public class MySqlSettings
{
public string User { get; set; }
public string Password { get; set; }
public string Host { get; set; }
public string Database { get; set; }
public int Port { get; set; } = 3306;
public string GetConnectionString()
{
return $"Server={Host};Database={Database};Port={Port};Uid={User};Pwd={Password}";
}
}
public ServiceBusAppSettings ServiceBus { get; set; } = new ServiceBusAppSettings();
public ApiSettings Api { get; set; } = new ApiSettings();
public MySqlSettings MySql { get; set; } = new MySqlSettings();
// Static load helper methods. These could also be moved to a factory class.
public static IConfigurationRoot GetConfiguration(string dir)
{
return GetConfiguration(dir, null);
}
public static IConfigurationRoot GetConfiguration(string dir, string environmentName)
{
if (string.IsNullOrEmpty(environmentName))
environmentName = "Development";
var builder = new ConfigurationBuilder()
.SetBasePath(dir)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{environmentName}.json", true)
.AddEnvironmentVariables();
return builder.Build();
}
public static AppSettings GetSettings(string dir)
{
return GetSettings(dir, null);
}
public static AppSettings GetSettings(string dir, string environmentName)
{
var config = GetConfiguration(dir, environmentName);
return GetSettings(config);
}
public static AppSettings GetSettings(IConfiguration config)
{
return config.Get<AppSettings>();
}
}
}
ASP.NET Core Startup.cs
:(获取 strongly-typed 设置对象在配置其他服务的这个阶段通常很有帮助。 ..)
public class Startup
{
public Startup(IHostingEnvironment env)
{
Configuration = AppSettings.GetConfiguration(env.ContentRootPath, env.EnvironmentName);
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Configure the service collection.
services.AddOptions();
services.Configure<AppSettings>(Configuration);
// It can also be handy to get the AppSettings object here.
var settings = AppSettings.GetSettings(Configuration);
// Add framework services.
services.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
// Pretty-print JSON in Development
options.SerializerSettings.Formatting = settings.Api.FormatJson ? Formatting.Indented : Formatting.None;
});
// Store DB connection info in AppSettings too...
var conn = settings.MySql.GetConnectionString();
services.AddDbContext<MyDbContext>(opt => opt.UseMySql(conn));
}
}
测试中Class:
var testDir = AppContext.BaseDirectory;
var settings = AppSettings.GetSettings(testDir, "Test");
//Act
var commandBus = new QueueCommandBus(settings);