You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
9.0 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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("JsonAppName", 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()
{
}
}
}