|
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
|
using Microsoft.Extensions.Hosting;
|
|
|
|
|
using Microsoft.Extensions.Hosting.Internal;
|
|
|
|
|
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
|
|
|
|
|
using Xunit;
|
|
|
|
|
|
|
|
|
|
namespace OptionsPattern.Sutdy.Experience
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 6.1 配置选项 编程体验
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class OptionsPatternTest:IDisposable
|
|
|
|
|
{
|
|
|
|
|
private readonly ITestOutputHelper testOutput;
|
|
|
|
|
public OptionsPatternTest(ITestOutputHelper outputHelper)
|
|
|
|
|
{
|
|
|
|
|
testOutput = outputHelper;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Test()
|
|
|
|
|
{
|
|
|
|
|
testOutput.WriteLine("6.1 配置选项 编程体验");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 将配置绑定为 Option 对象
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void BindConfiguration_As_OptionsObject_Test()
|
|
|
|
|
{
|
|
|
|
|
var configuration = new ConfigurationBuilder().AddJsonFile("Configs/appsettings.json",false,true).Build();
|
|
|
|
|
|
|
|
|
|
var appOption = new ServiceCollection()
|
|
|
|
|
.AddOptions()
|
|
|
|
|
.Configure<AppOption>(configuration)
|
|
|
|
|
.BuildServiceProvider()
|
|
|
|
|
.GetRequiredService<IOptions<AppOption>>().Value;
|
|
|
|
|
|
|
|
|
|
Assert.NotNull(configuration);
|
|
|
|
|
Assert.NotNull(appOption);
|
|
|
|
|
|
|
|
|
|
Assert.Equal("JsonAppNmae", appOption.AppName);
|
|
|
|
|
Assert.Equal(new Version(0,0,0,1), appOption.AppVersion);
|
|
|
|
|
Assert.Equal("json@163.com", appOption.EMail?.ReceiveAddress);
|
|
|
|
|
Assert.Equal("json", appOption.EMail?.Recipient);
|
|
|
|
|
|
|
|
|
|
testOutput.WriteLine("将配置绑定为 Option 对象");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 提供具名的 Options 对象
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Provide_NamedOptionsObject_Test()
|
|
|
|
|
{
|
|
|
|
|
var memoryData = new Dictionary<string, string?>()
|
|
|
|
|
{
|
|
|
|
|
["One:AppName"] = "OneAppName",
|
|
|
|
|
["One:AppVersion"] = "1.1.1.1",
|
|
|
|
|
["One:EMail:ReceiveAddress"] = "One@163.com",
|
|
|
|
|
["One:EMail:Recipient"] = "One",
|
|
|
|
|
|
|
|
|
|
["Two:AppName"] = "TwoAppName",
|
|
|
|
|
["Two:AppVersion"] = "2.2.2.2",
|
|
|
|
|
["Two:EMail:ReceiveAddress"] = "Two@163.com",
|
|
|
|
|
["Two:EMail:Recipient"] = "Two",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var configuration = new ConfigurationBuilder().AddInMemoryCollection(memoryData).Build();
|
|
|
|
|
|
|
|
|
|
var serviceProvider = new ServiceCollection()
|
|
|
|
|
.AddOptions()
|
|
|
|
|
.Configure<AppOption>("One", configuration.GetSection("One"))
|
|
|
|
|
.Configure<AppOption>("Two", configuration.GetSection("Two"))
|
|
|
|
|
.BuildServiceProvider();
|
|
|
|
|
|
|
|
|
|
var optionsSnapshot = serviceProvider.GetRequiredService<IOptionsSnapshot<AppOption>>();
|
|
|
|
|
|
|
|
|
|
var one = optionsSnapshot.Get("One");
|
|
|
|
|
var two = optionsSnapshot.Get("Two");
|
|
|
|
|
|
|
|
|
|
Assert.NotNull(one);
|
|
|
|
|
Assert.NotNull(two);
|
|
|
|
|
|
|
|
|
|
Assert.Equal("OneAppName", one.AppName);
|
|
|
|
|
Assert.Equal(new Version(1,1,1,1), one.AppVersion);
|
|
|
|
|
Assert.Equal("One@163.com", one.EMail?.ReceiveAddress);
|
|
|
|
|
Assert.Equal("One", one.EMail?.Recipient);
|
|
|
|
|
|
|
|
|
|
Assert.Equal("TwoAppName", two.AppName);
|
|
|
|
|
Assert.Equal(new Version(2, 2, 2, 2), two.AppVersion);
|
|
|
|
|
Assert.Equal("Two@163.com", two.EMail?.ReceiveAddress);
|
|
|
|
|
Assert.Equal("Two", two.EMail?.Recipient);
|
|
|
|
|
|
|
|
|
|
testOutput.WriteLine("提供具名的 Options 对象");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 直接初始化 Options 对象
|
|
|
|
|
/// (不使用IConfiguration)
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void IniOptions_NoConfiguration_Test()
|
|
|
|
|
{
|
|
|
|
|
var appOption = new ServiceCollection()
|
|
|
|
|
.AddOptions()
|
|
|
|
|
.Configure<AppOption>(configOption =>
|
|
|
|
|
{
|
|
|
|
|
configOption.AppName = "NoConfigurationAppName";
|
|
|
|
|
configOption.AppVersion = new Version(0, 0, 0, 1);
|
|
|
|
|
configOption.EMail = new ReceiveMailOption()
|
|
|
|
|
{
|
|
|
|
|
ReceiveAddress = "NoConfigurationAppName@163.com",
|
|
|
|
|
Recipient = "NoConfigurationAppName",
|
|
|
|
|
};
|
|
|
|
|
})
|
|
|
|
|
.BuildServiceProvider()
|
|
|
|
|
.GetRequiredService<IOptions<AppOption>>().Value;
|
|
|
|
|
|
|
|
|
|
Assert.NotNull(appOption);
|
|
|
|
|
|
|
|
|
|
Assert.Equal("NoConfigurationAppName", appOption.AppName);
|
|
|
|
|
Assert.Equal(new Version(0, 0, 0, 1), appOption.AppVersion);
|
|
|
|
|
Assert.Equal("NoConfigurationAppName@163.com", appOption.EMail?.ReceiveAddress);
|
|
|
|
|
Assert.Equal("NoConfigurationAppName", appOption.EMail?.Recipient);
|
|
|
|
|
|
|
|
|
|
testOutput.WriteLine("直接初始化 Options 对象");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 根据依赖服务的 Options 设置
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Theory]
|
|
|
|
|
[InlineData("pro")]
|
|
|
|
|
[InlineData("dev")]
|
|
|
|
|
[InlineData("test")]
|
|
|
|
|
public void SetOptions_By_DependentService_Test(string environmentName)
|
|
|
|
|
{
|
|
|
|
|
var services = new ServiceCollection();
|
|
|
|
|
services
|
|
|
|
|
.AddSingleton<IHostEnvironment>(new HostingEnvironment() { EnvironmentName = environmentName })
|
|
|
|
|
.AddOptions<AppOption>()// AddOptions() 与 AddOptions<TOption>() 返回的类型不一样。之后的 Configure 扩展不一样
|
|
|
|
|
.Configure<IHostEnvironment>((appOption, hostEnv) => // 泛型参数确定 Action 参数
|
|
|
|
|
{
|
|
|
|
|
appOption.AppName = hostEnv.EnvironmentName + nameof(appOption.AppName);
|
|
|
|
|
appOption.AppVersion = new Version();
|
|
|
|
|
appOption.EMail = new ReceiveMailOption()
|
|
|
|
|
{
|
|
|
|
|
ReceiveAddress = $"{hostEnv.EnvironmentName}@163.com",
|
|
|
|
|
Recipient = hostEnv.EnvironmentName,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
var appOption = services
|
|
|
|
|
.BuildServiceProvider()
|
|
|
|
|
.GetRequiredService< IOptions<AppOption> >()
|
|
|
|
|
.Value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Assert.NotNull(appOption);
|
|
|
|
|
Assert.Equal($"{environmentName}AppName",appOption.AppName);
|
|
|
|
|
Assert.Equal(new Version(),appOption.AppVersion);
|
|
|
|
|
Assert.Equal($"{environmentName}@163.com",appOption.EMail?.ReceiveAddress);
|
|
|
|
|
Assert.Equal($"{environmentName}",appOption.EMail?.Recipient);
|
|
|
|
|
|
|
|
|
|
testOutput.WriteLine("根据依赖服务的 Options 设置");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 验证 Options 的有效性:通过
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Validate_Options_Success_Test()
|
|
|
|
|
{
|
|
|
|
|
var services = new ServiceCollection();
|
|
|
|
|
services
|
|
|
|
|
.AddOptions<AppOption>()
|
|
|
|
|
.Configure(configOption =>
|
|
|
|
|
{
|
|
|
|
|
configOption.AppName = "ValidateAppName";
|
|
|
|
|
configOption.AppVersion = new Version(0, 0, 0, 1);
|
|
|
|
|
configOption.EMail = new ReceiveMailOption()
|
|
|
|
|
{
|
|
|
|
|
ReceiveAddress = "Validate@163.com",
|
|
|
|
|
Recipient = "Validate",
|
|
|
|
|
};
|
|
|
|
|
})
|
|
|
|
|
.Validate(option =>
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
//不发生异常
|
|
|
|
|
Action codeSnippet = () =>
|
|
|
|
|
{
|
|
|
|
|
_ = services
|
|
|
|
|
.BuildServiceProvider()
|
|
|
|
|
.GetService<IOptions<AppOption>>()
|
|
|
|
|
?.Value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var exception = Record.Exception(codeSnippet);
|
|
|
|
|
Assert.Null(exception);
|
|
|
|
|
|
|
|
|
|
testOutput.WriteLine("验证 Options 的有效性:通过");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 验证 Options 的有效性:无效并引发异常
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Validate_Options_Fail_Test()
|
|
|
|
|
{
|
|
|
|
|
var services = new ServiceCollection();
|
|
|
|
|
services
|
|
|
|
|
.AddOptions<AppOption>()
|
|
|
|
|
.Configure(configOption =>
|
|
|
|
|
{
|
|
|
|
|
configOption.AppName = "ValidateAppName";
|
|
|
|
|
configOption.AppVersion = new Version(0, 0, 0, 1);
|
|
|
|
|
configOption.EMail = new ReceiveMailOption()
|
|
|
|
|
{
|
|
|
|
|
ReceiveAddress = "Validate@163.com",
|
|
|
|
|
Recipient = "Validate",
|
|
|
|
|
};
|
|
|
|
|
})
|
|
|
|
|
.Validate(option => //返回false,表示验证错误,会抛出异常
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
//引发异常
|
|
|
|
|
Assert.Throws<OptionsValidationException>(() =>
|
|
|
|
|
{
|
|
|
|
|
_ = services
|
|
|
|
|
.BuildServiceProvider()
|
|
|
|
|
.GetService<IOptions<AppOption>>()
|
|
|
|
|
?.Value;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
testOutput.WriteLine("验证 Options 的有效性:无效并引发异常");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|