Files
2026-09-02 09:38:45 +08:00

118 lines
6.0 KiB
C#

using Yh.Platform.Abstractions;
using Yh.Platform.OpenApi;
using Xunit;
namespace Yh.Platform.OpenApi.Tests;
public class OpenApiOptionsTests
{
[Theory]
[InlineData(null, null)]
[InlineData("", null)]
[InlineData(" ", null)]
[InlineData("/userbase", "/userbase")]
[InlineData("/userbase/", "/userbase")]
[InlineData("userbase", "/userbase")]
public void NormalizeBasePath_归一化规则(string? input, string? expected)
{
Assert.Equal(expected, OpenApiOptions.NormalizeBasePath(input));
}
[Fact]
public void ResolveBaseUrl_拼接host与path并去尾斜杠()
{
var options = new OpenApiOptions { BaseHost = "http://base.bestsch.com/", BasePath = "/userbase/" };
Assert.Equal("http://base.bestsch.com/userbase", options.ResolveBaseUrl());
}
[Fact]
public void ResolveBaseUrl_path为空时挂根路径()
{
var options = new OpenApiOptions { BaseHost = "http://base.bestsch.com", BasePath = "" };
Assert.Equal("http://base.bestsch.com", options.ResolveBaseUrl());
}
[Fact]
public void 默认值_对齐Java客户端()
{
var options = new OpenApiOptions();
Assert.True(options.Enabled);
Assert.Equal("/userbase", options.BasePath);
Assert.Equal(1500, options.ConnectTimeoutMs);
Assert.Equal(5000, options.ReadTimeoutMs);
Assert.Equal(5000, options.WriteTimeoutMs);
}
}
/// <summary>静态门面 <see cref="YschBaseOpenApi"/> 的初始化准入与委托行为。</summary>
public class YschBaseOpenApiTests : IDisposable
{
private sealed class StubUserClient : IOpenApiUserClient
{
public int Calls;
public Task<BoaUser?> GetUserInfoAsync(int userId, CancellationToken ct = default)
{
Calls++;
return Task.FromResult<BoaUser?>(new BoaUser(userId, "stub", "桩用户"));
}
public Task<BoaUser?> GetUserByIdAsync(string userId, CancellationToken ct = default) => throw new NotImplementedException();
public Task<BoaUser?> GetUserByLoginNameAsync(string loginName, CancellationToken ct = default) => throw new NotImplementedException();
public Task<BoaUser?> GetUserByPhoneAsync(string phone, CancellationToken ct = default) => throw new NotImplementedException();
public Task<BoaUser?> GetUserInfoAsync(string loginName, CancellationToken ct = default) => throw new NotImplementedException();
public Task<List<BoaModule>> GetUserModuleAsync(int userId, int? schoolId = null, CancellationToken ct = default) => throw new NotImplementedException();
public Task<BoaUser?> AddUserAsync(SysUserRequest request, CancellationToken ct = default) => throw new NotImplementedException();
public Task<BoaUser?> EditUserAsync(int id, SysUserRequest request, CancellationToken ct = default) => throw new NotImplementedException();
public Task DeleteUserAsync(int id, int groupId, int schoolId, CancellationToken ct = default) => throw new NotImplementedException();
public Task DeleteUsersAsync(IReadOnlyList<SysUserGroupDeleteItem> items, CancellationToken ct = default) => throw new NotImplementedException();
public Task<List<BoaUser>> BatchAddUsersAsync(IReadOnlyList<SysUserRequest> requests, CancellationToken ct = default) => throw new NotImplementedException();
public Task<BoaUser?> MoveUserToGroupAsync(SysUserMoveRequest request, CancellationToken ct = default) => throw new NotImplementedException();
public Task<List<BoaRoleInfo>> GetUserRoleListAsync(int userId, CancellationToken ct = default) => throw new NotImplementedException();
public Task<BoaRoleInfo?> GetCurrentIdentityAsync(int userId, CancellationToken ct = default) => throw new NotImplementedException();
public Task<List<BoaRoleInfo>> GetAvailableIdentitiesAsync(int userId, CancellationToken ct = default) => throw new NotImplementedException();
public Task<BoaRoleInfo?> SwitchIdentityAsync(int userId, int roleId, int schoolId, CancellationToken ct = default) => throw new NotImplementedException();
public Task UpdateUserPasswordAsync(int userId, string oldPassword, string newPassword, CancellationToken ct = default) => throw new NotImplementedException();
public Task SetUserGroupStateAsync(SysUserGroupStateRequest request, CancellationToken ct = default) => throw new NotImplementedException();
public Task<int?> GetUserGroupStateAsync(int userId, int groupId, int schoolId, CancellationToken ct = default) => throw new NotImplementedException();
public Task<BoaUser?> TransferUserToSchoolAsync(SysUserTransferSchoolRequest request, CancellationToken ct = default) => throw new NotImplementedException();
public Task ChangeUserStatusAsync(int userId, bool disabled, CancellationToken ct = default) => throw new NotImplementedException();
public Task BatchChangeUserStatusAsync(IReadOnlyList<int> userIds, bool disabled, CancellationToken ct = default) => throw new NotImplementedException();
}
public YschBaseOpenApiTests()
{
YschBaseOpenApi.SetUserClient(null);
YschBaseOpenApi.SetGroupClient(null);
YschBaseOpenApi.SetAppClient(null);
}
public void Dispose()
{
YschBaseOpenApi.SetUserClient(null);
YschBaseOpenApi.SetGroupClient(null);
YschBaseOpenApi.SetAppClient(null);
}
[Fact]
public async Task 未初始化时抛InvalidOperationException并给出引导信息()
{
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => YschBaseOpenApi.GetUserInfoAsync(1));
Assert.Contains("AddYhOpenApi", ex.Message);
Assert.Contains("SetUserClient", ex.Message);
}
[Fact]
public async Task 初始化后门面委托到注入的client()
{
var stub = new StubUserClient();
YschBaseOpenApi.SetUserClient(stub);
var user = await YschBaseOpenApi.GetUserInfoAsync(1001);
Assert.Equal(1, stub.Calls);
Assert.NotNull(user);
Assert.Equal(1001, user!.Id);
Assert.Equal("stub", user.Account);
}
}