using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Yh.SchClass.OpenApi.Tests;
///
/// 配置读取测试:对应 appsettings.json 的真实结构 ——
///
/// "yh": { "open": {
/// "BaseHost": "http://base.yunhaixingtong.com",
/// "BasePath": "/userbase", // UserBase 用,教务不用它
/// "SchClassPath": "/bschclass" // 教务用它
/// }}
///
///
public class SchClassOpenApiConfigTests
{
private static IConfiguration BuildConfig(Dictionary kv)
=> new ConfigurationBuilder().AddInMemoryCollection(kv).Build()!;
[Fact]
public void 共享节_SchClassPath映射为教务BasePath()
{
var config = BuildConfig(new Dictionary
{
["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
{
["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
{
["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
{
["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
{
["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>().Value;
Assert.Equal("http://base.yunhaixingtong.com/bschclass", options.ResolveBaseUrl());
var facade = provider.GetRequiredService();
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
{
["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>().Value;
Assert.Equal("http://sch.example.com", options.BaseHost);
Assert.Equal("/sch", options.BasePath);
Assert.Equal(3000, options.ReadTimeoutMs);
}
}