bag
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Yh.SchClass.OpenApi.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// 配置读取测试:对应 appsettings.json 的真实结构 ——
|
||||
/// <code>
|
||||
/// "yh": { "open": {
|
||||
/// "BaseHost": "http://base.yunhaixingtong.com",
|
||||
/// "BasePath": "/userbase", // UserBase 用,教务不用它
|
||||
/// "SchClassPath": "/bschclass" // 教务用它
|
||||
/// }}
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public class SchClassOpenApiConfigTests
|
||||
{
|
||||
private static IConfiguration BuildConfig(Dictionary<string, string?> kv)
|
||||
=> new ConfigurationBuilder().AddInMemoryCollection(kv).Build()!;
|
||||
|
||||
[Fact]
|
||||
public void 共享节_SchClassPath映射为教务BasePath()
|
||||
{
|
||||
var config = BuildConfig(new Dictionary<string, string?>
|
||||
{
|
||||
["yh:open:BaseHost"] = "http://base.yunhaixingtong.com",
|
||||
["yh:open:BasePath"] = "/userbase",
|
||||
["yh:open:SchClassPath"] = "/bschclass",
|
||||
});
|
||||
|
||||
var options = new SchClassOpenApiOptions();
|
||||
var shared = config.GetSection(SchClassOpenApiOptions.SharedSectionName);
|
||||
options.FillFromSharedSection(key => shared[key]);
|
||||
|
||||
Assert.Equal("http://base.yunhaixingtong.com", options.BaseHost);
|
||||
// 关键:教务用 SchClassPath,不是共享节里的 BasePath(/userbase)
|
||||
Assert.Equal("/bschclass", options.BasePath);
|
||||
Assert.Equal("http://base.yunhaixingtong.com/bschclass", options.ResolveBaseUrl());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 共享节_路径带空格与斜杠可归一化()
|
||||
{
|
||||
var config = BuildConfig(new Dictionary<string, string?>
|
||||
{
|
||||
["yh:open:BaseHost"] = "http://base.yunhaixingtong.com",
|
||||
["yh:open:SchClassPath"] = " /bschclass/", // 模拟配置里常见的多余空格/尾斜杠
|
||||
});
|
||||
|
||||
var options = new SchClassOpenApiOptions();
|
||||
var shared = config.GetSection(SchClassOpenApiOptions.SharedSectionName);
|
||||
options.FillFromSharedSection(key => shared[key]);
|
||||
|
||||
Assert.Equal("/bschclass", options.BasePath);
|
||||
Assert.Equal("http://base.yunhaixingtong.com/bschclass", options.ResolveBaseUrl());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 共享节_未配SchClassPath时BasePath保持空()
|
||||
{
|
||||
var config = BuildConfig(new Dictionary<string, string?>
|
||||
{
|
||||
["yh:open:BaseHost"] = "http://base.yunhaixingtong.com",
|
||||
["yh:open:BasePath"] = "/userbase", // 不允许被教务误用
|
||||
});
|
||||
|
||||
var options = new SchClassOpenApiOptions();
|
||||
var shared = config.GetSection(SchClassOpenApiOptions.SharedSectionName);
|
||||
options.FillFromSharedSection(key => shared[key]);
|
||||
|
||||
Assert.Equal("http://base.yunhaixingtong.com", options.BaseHost);
|
||||
Assert.Null(options.BasePath);
|
||||
Assert.Equal("http://base.yunhaixingtong.com", options.ResolveBaseUrl());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 独立节优先_共享节仅回填缺失项()
|
||||
{
|
||||
var config = BuildConfig(new Dictionary<string, string?>
|
||||
{
|
||||
["yh:schclass:open:BasePath"] = "/sch-only", // 独立节只给了路径
|
||||
["yh:open:BaseHost"] = "http://base.yunhaixingtong.com",
|
||||
["yh:open:SchClassPath"] = "/bschclass",
|
||||
["yh:open:AppKey"] = "100002",
|
||||
["yh:open:AppSecret"] = "secret",
|
||||
});
|
||||
|
||||
var options = new SchClassOpenApiOptions();
|
||||
config.GetSection(SchClassOpenApiOptions.SectionName).Bind(options);
|
||||
var shared = config.GetSection(SchClassOpenApiOptions.SharedSectionName);
|
||||
options.FillFromSharedSection(key => shared[key]);
|
||||
|
||||
Assert.Equal("http://base.yunhaixingtong.com", options.BaseHost); // 从共享节回填
|
||||
Assert.Equal("/sch-only", options.BasePath); // 独立节优先,不被覆盖
|
||||
Assert.Equal("100002", options.AppKey); // AppKey 回填
|
||||
Assert.Equal("secret", options.AppSecret);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DI_注册后可解析门面且地址来自配置()
|
||||
{
|
||||
var config = BuildConfig(new Dictionary<string, string?>
|
||||
{
|
||||
["yh:open:BaseHost"] = "http://base.yunhaixingtong.com",
|
||||
["yh:open:SchClassPath"] = "/bschclass",
|
||||
});
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSchClassOpenApi(config);
|
||||
using var provider = services.BuildServiceProvider();
|
||||
|
||||
var options = provider.GetRequiredService<IOptions<SchClassOpenApiOptions>>().Value;
|
||||
Assert.Equal("http://base.yunhaixingtong.com/bschclass", options.ResolveBaseUrl());
|
||||
|
||||
var facade = provider.GetRequiredService<SchClassOpenApi>();
|
||||
Assert.NotNull(facade.SchInfo);
|
||||
Assert.NotNull(facade.StuInfo);
|
||||
Assert.Equal(new Uri("http://base.yunhaixingtong.com/bschclass"), facade.HttpBaseAddress);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DI_独立节配置整节生效()
|
||||
{
|
||||
var config = BuildConfig(new Dictionary<string, string?>
|
||||
{
|
||||
["yh:schclass:open:BaseHost"] = "http://sch.example.com",
|
||||
["yh:schclass:open:BasePath"] = "/sch",
|
||||
["yh:schclass:open:ReadTimeoutMs"] = "3000",
|
||||
["yh:open:BaseHost"] = "http://base.yunhaixingtong.com",
|
||||
});
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSchClassOpenApi(config);
|
||||
using var provider = services.BuildServiceProvider();
|
||||
|
||||
var options = provider.GetRequiredService<IOptions<SchClassOpenApiOptions>>().Value;
|
||||
Assert.Equal("http://sch.example.com", options.BaseHost);
|
||||
Assert.Equal("/sch", options.BasePath);
|
||||
Assert.Equal(3000, options.ReadTimeoutMs);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user