From fb7c1392a131f0224f29b0c91f742a05a07c88cb Mon Sep 17 00:00:00 2001 From: yubaolee Date: Sun, 30 Nov 2025 21:22:10 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9Bfix:=20=E5=8A=A8=E6=80=81API?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E5=A4=A7=E5=B0=8F=E5=86=99=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenAuth.App/DynamicApiApp/DynamicApiApp.cs | 167 ++++-- OpenAuth.App/Test/TestDynamicApiApp.cs | 628 +++++++++++++++++++- 2 files changed, 722 insertions(+), 73 deletions(-) diff --git a/OpenAuth.App/DynamicApiApp/DynamicApiApp.cs b/OpenAuth.App/DynamicApiApp/DynamicApiApp.cs index 865666e6..d5a4ab5a 100644 --- a/OpenAuth.App/DynamicApiApp/DynamicApiApp.cs +++ b/OpenAuth.App/DynamicApiApp/DynamicApiApp.cs @@ -8,6 +8,7 @@ using OpenAuth.App.Response; using SqlSugar; using OpenAuth.App.Request; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; namespace OpenAuth.App { @@ -31,6 +32,59 @@ namespace OpenAuth.App this.logger = logger; } + #region 辅助方法 - 大小写不敏感的字典操作 + + /// + /// 将普通字典转换为大小写不敏感的字典 + /// + private Dictionary ToIgnoreCaseDict(Dictionary source) + { + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + if (source != null) + { + foreach (var kvp in source) + { + result[kvp.Key] = kvp.Value; + } + } + return result; + } + + /// + /// 检查字典中是否包含指定键(大小写不敏感) + /// + private bool ContainsKeyIgnoreCase(Dictionary dict, string key) + { + return dict.Keys.Any(k => string.Equals(k, key, StringComparison.OrdinalIgnoreCase)); + } + + /// + /// 获取字典中指定键的值(大小写不敏感) + /// + private object GetValueIgnoreCase(Dictionary dict, string key) + { + var kvp = dict.FirstOrDefault(x => string.Equals(x.Key, key, StringComparison.OrdinalIgnoreCase)); + return kvp.Value; + } + + /// + /// 设置字典中指定键的值(保留原始键名,大小写不敏感查找) + /// + private void SetValueIgnoreCase(Dictionary dict, string key, object value) + { + var existingKey = dict.Keys.FirstOrDefault(k => string.Equals(k, key, StringComparison.OrdinalIgnoreCase)); + if (existingKey != null) + { + dict[existingKey] = value; + } + else + { + dict[key] = value; + } + } + + #endregion + /// /// 获取表数据列表 /// @@ -154,37 +208,42 @@ namespace OpenAuth.App return result; } - // 将对象转换为字典 - var dict = JsonHelper.Instance.Deserialize>(req.Obj); + // 将对象转换为字典(使用大小写不敏感的反序列化) + var rawDict = JsonConvert.DeserializeObject>(req.Obj); + var dict = ToIgnoreCaseDict(rawDict); - // 设置ID - if (!dict.ContainsKey("Id")) - { - dict["Id"] = Guid.NewGuid().ToString(); - } - else if (string.IsNullOrEmpty(dict["Id"]?.ToString())) + // 设置ID(大小写不敏感检查) + if (!ContainsKeyIgnoreCase(dict, "Id")) { dict["Id"] = Guid.NewGuid().ToString(); } else { - //如果Id不为空,需要判断Id是否存在 - var entity = await _client.Queryable() - .AS(req.TableName) - .Where("Id = @id", new { id = dict["Id"] }) - .FirstAsync(); - if (entity != null) + var idValue = GetValueIgnoreCase(dict, "Id"); + if (string.IsNullOrEmpty(idValue?.ToString())) { - result.Code = 500; - result.Message = "Id已存在"; - return result; + SetValueIgnoreCase(dict, "Id", Guid.NewGuid().ToString()); + } + else + { + //如果Id不为空,需要判断Id是否存在 + var entity = await _client.Queryable() + .AS(req.TableName) + .Where("Id = @id", new { id = idValue }) + .FirstAsync(); + if (entity != null) + { + result.Code = 500; + result.Message = "Id已存在"; + return result; + } } } - //如果有CreateTime字段,自动设置 - if (dict.ContainsKey("CreateTime")) + //如果有CreateTime字段,自动设置(大小写不敏感) + if (ContainsKeyIgnoreCase(dict, "CreateTime")) { - dict["CreateTime"] = DateTime.Now.ToString(); + SetValueIgnoreCase(dict, "CreateTime", DateTime.Now.ToString()); } // 添加数据 @@ -222,30 +281,44 @@ namespace OpenAuth.App return result; } - // 将对象转换为字典 - var dict = JsonHelper.Instance.Deserialize>(req.Obj); + // 将对象转换为字典(使用大小写不敏感的反序列化) + var rawDict = JsonConvert.DeserializeObject>(req.Obj); + var dict = ToIgnoreCaseDict(rawDict); - // 检查ID是否存在 - if (!dict.ContainsKey("Id")) + // 检查ID是否存在(大小写不敏感) + if (!ContainsKeyIgnoreCase(dict, "Id")) { result.Code = 500; result.Message = "更新数据必须包含Id字段"; return result; } - // 如果有UpdateTime字段,自动设置 - if (dict.ContainsKey("UpdateTime")) + // 确保字典中有 "Id" 键(用于 SqlSugar 的 WhereColumns) + if (!dict.ContainsKey("Id")) { - dict["UpdateTime"] = DateTime.Now.ToString(); + var idValue = GetValueIgnoreCase(dict, "Id"); + // 移除原始的小写 id 键 + var originalKey = dict.Keys.FirstOrDefault(k => string.Equals(k, "Id", StringComparison.OrdinalIgnoreCase)); + if (originalKey != null && originalKey != "Id") + { + dict.Remove(originalKey); + dict["Id"] = idValue; + } } - // 如果有用户信息,设置更新用户 + // 如果有UpdateTime字段,自动设置(大小写不敏感) + if (ContainsKeyIgnoreCase(dict, "UpdateTime")) + { + SetValueIgnoreCase(dict, "UpdateTime", DateTime.Now.ToString()); + } + + // 如果有用户信息,设置更新用户(大小写不敏感) var currentUser = _auth.GetCurrentUser(); - if (dict.ContainsKey("UpdateUserId") && currentUser != null) + if (ContainsKeyIgnoreCase(dict, "UpdateUserId") && currentUser != null) { // 设置更新用户信息 - dict["UpdateUserId"] = currentUser.User.Id; - dict["UpdateUserName"] = currentUser.User.Name; + SetValueIgnoreCase(dict, "UpdateUserId", currentUser.User.Id); + SetValueIgnoreCase(dict, "UpdateUserName", currentUser.User.Name); } // 更新数据 @@ -387,27 +460,21 @@ namespace OpenAuth.App try { var json = request.Parameters; - // 检查参数名是否存在于JSON中 - if (json.Contains($"\"{param.Name}\"")) + + // 解析完整的JSON对象(使用大小写不敏感的字典) + var jsonObj = JsonConvert.DeserializeObject>(json); + var ignoreCaseDict = ToIgnoreCaseDict(jsonObj); + + // 从JSON对象中获取参数值(大小写不敏感查找) + if (ContainsKeyIgnoreCase(ignoreCaseDict, param.Name)) { - // 解析完整的JSON对象 - var jsonObj = JsonHelper.Instance.Deserialize>(json); + // 获取参数对应的JSON值并序列化为字符串 + var rawValue = GetValueIgnoreCase(ignoreCaseDict, param.Name); + var paramValue = JsonHelper.Instance.Serialize(rawValue); - // 从JSON对象中获取参数值 - if (jsonObj.ContainsKey(param.Name)) - { - // 获取参数对应的JSON值并序列化为字符串 - var paramValue = JsonHelper.Instance.Serialize(jsonObj[param.Name]); - - // 将JSON字符串反序列化为目标类型 - var deserializeMethod = typeof(JsonHelper).GetMethod("Deserialize").MakeGenericMethod(param.ParameterType); - paramValues[i] = deserializeMethod.Invoke(JsonHelper.Instance, new object[] { paramValue }); - } - else - { - // 参数名存在但获取不到,使用默认值 - paramValues[i] = param.HasDefaultValue ? param.DefaultValue : null; - } + // 将JSON字符串反序列化为目标类型 + var deserializeMethod = typeof(JsonHelper).GetMethod("Deserialize").MakeGenericMethod(param.ParameterType); + paramValues[i] = deserializeMethod.Invoke(JsonHelper.Instance, new object[] { paramValue }); } else { diff --git a/OpenAuth.App/Test/TestDynamicApiApp.cs b/OpenAuth.App/Test/TestDynamicApiApp.cs index ff4dd7e8..d9356af9 100644 --- a/OpenAuth.App/Test/TestDynamicApiApp.cs +++ b/OpenAuth.App/Test/TestDynamicApiApp.cs @@ -11,8 +11,17 @@ using OpenAuth.App.SSO; namespace OpenAuth.App.Test { - class TestDynamicApiApp :TestBase + /// + /// DynamicApiApp 单元测试 + /// 测试表:noentity (id varchar(50), name varchar(255), age int) + /// 支持 MySQL 和 SqlServer 数据库 + /// 测试大小写混合属性命名 + /// + [TestFixture] + public class TestDynamicApiApp : TestBase { + private const string TEST_TABLE = "noentity"; + public override ServiceCollection GetService() { var services = new ServiceCollection(); @@ -28,55 +37,628 @@ namespace OpenAuth.App.Test return services; } - + + + #region 基础 CRUD 测试 + + /// + /// 测试添加数据 - 标准属性名(PascalCase) + /// [Test] - public async Task TestAdd() + public async Task TestAdd_PascalCase() { var app = _autofacServiceProvider.GetService(); - var obj = await app.Add(new AddOrUpdateDynamicEntityReq { TableName = "noentity", Obj = "{\"P1\":\"测试\",\"Id\":\"12\"}" }); - Console.WriteLine(JsonHelper.Instance.Serialize(obj)); + var id = Guid.NewGuid().ToString(); + + var result = await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"测试PascalCase\",\"Age\":25}}" + }); + + Console.WriteLine($"添加结果(PascalCase): {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"添加失败: {result.Message}"); + } + /// + /// 测试添加数据 - 小写属性名(camelCase) + /// + [Test] + public async Task TestAdd_CamelCase() + { + var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + + var result = await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"id\":\"{id}\",\"name\":\"测试camelCase\",\"age\":30}}" + }); + + Console.WriteLine($"添加结果(camelCase): {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"添加失败: {result.Message}"); + + + } + + /// + /// 测试添加数据 - 大写属性名(UPPERCASE) + /// + [Test] + public async Task TestAdd_UpperCase() + { + var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + + var result = await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"ID\":\"{id}\",\"NAME\":\"测试UPPERCASE\",\"AGE\":35}}" + }); + + Console.WriteLine($"添加结果(UPPERCASE): {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"添加失败: {result.Message}"); + + + } + + /// + /// 测试添加数据 - 混合大小写属性名(MixedCase) + /// + [Test] + public async Task TestAdd_MixedCase() + { + var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + + // 混合使用不同大小写:Id(PascalCase), name(camelCase), AGE(UPPERCASE) + var result = await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"name\":\"测试MixedCase\",\"AGE\":40}}" + }); + + Console.WriteLine($"添加结果(MixedCase): {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"添加失败: {result.Message}"); + + + } + + /// + /// 测试获取单条数据 + /// [Test] public async Task TestGet() { var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + + // 先添加数据 + await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"测试获取\",\"Age\":28}}" + }); + + // 获取数据 + var result = await app.Get(new QueryDynamicEntityReq + { + TableName = TEST_TABLE, + Id = id + }); + + Console.WriteLine($"获取结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"获取失败: {result.Message}"); + Assert.That(result.Data, Is.Not.Null, "未找到数据"); + - var obj = await app.Get(new QueryDynamicEntityReq { TableName = "noentity", Id = "1" }); - Console.WriteLine(JsonHelper.Instance.Serialize(obj)); } + /// + /// 测试获取列表 + /// [Test] public async Task TestGetList() { var app = _autofacServiceProvider.GetService(); - var obj = await app.GetList(new QueryDynamicListReq { TableName = "noentity", page = 1, limit = 10, key = "" }); - Console.WriteLine(JsonHelper.Instance.Serialize(obj)); + var result = await app.GetList(new QueryDynamicListReq + { + TableName = TEST_TABLE, + page = 1, + limit = 10, + key = "" + }); + + Console.WriteLine($"列表查询结果: 总数={result.Count}, 数据条数={result.Data?.Count ?? 0}"); + Console.WriteLine($"详细结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"查询失败: {result.Message}"); } + /// + /// 测试带关键字搜索的列表查询 + /// [Test] - public async Task TestInvoke() + public async Task TestGetList_WithKey() + { + var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + var searchKey = "搜索测试_" + DateTime.Now.Ticks; + + // 先添加测试数据 + await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"{searchKey}\",\"Age\":22}}" + }); + + // 查询 + var result = await app.GetList(new QueryDynamicListReq + { + TableName = TEST_TABLE, + page = 1, + limit = 10, + key = searchKey + }); + + Console.WriteLine($"带关键字搜索结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"查询失败: {result.Message}"); + Assert.That(result.Count, Is.GreaterThanOrEqualTo(1), "应该至少找到一条数据"); + + // 清理测试数据 + await CleanupTestData(app, id); + } + + /// + /// 测试更新数据 - 标准属性名(PascalCase) + /// + [Test] + public async Task TestUpdate_PascalCase() + { + var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + + // 先添加数据 + await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"原始名称\",\"Age\":20}}" + }); + + // 更新数据 + var result = await app.Update(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"更新后PascalCase\",\"Age\":21}}" + }); + + Console.WriteLine($"更新结果(PascalCase): {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"更新失败: {result.Message}"); + + // 验证更新结果 + var getResult = await app.Get(new QueryDynamicEntityReq { TableName = TEST_TABLE, Id = id }); + Console.WriteLine($"更新后数据: {JsonHelper.Instance.Serialize(getResult)}"); + } + + /// + /// 测试更新数据 - 小写属性名(camelCase) + /// + [Test] + public async Task TestUpdate_CamelCase() + { + var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + + // 先添加数据 + await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"id\":\"{id}\",\"name\":\"原始名称\",\"age\":20}}" + }); + + // 更新数据 + var result = await app.Update(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"id\":\"{id}\",\"name\":\"更新后camelCase\",\"age\":22}}" + }); + + Console.WriteLine($"更新结果(camelCase): {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"更新失败: {result.Message}"); + } + + /// + /// 测试更新数据 - 混合大小写属性名 + /// + [Test] + public async Task TestUpdate_MixedCase() + { + var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + + // 先添加数据(使用PascalCase) + await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"原始名称\",\"Age\":20}}" + }); + + // 更新数据(使用混合大小写) + var result = await app.Update(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"name\":\"更新后MixedCase\",\"AGE\":23}}" + }); + + Console.WriteLine($"更新结果(MixedCase): {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"更新失败: {result.Message}"); + } + + /// + /// 测试删除单条数据 + /// + [Test] + public async Task TestDelete_Single() + { + var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + + // 先添加数据 + await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"待删除\",\"Age\":99}}" + }); + + // 删除数据 + var result = await app.Delete(new DelDynamicReq + { + TableName = TEST_TABLE, + Ids = new[] { id } + }); + + Console.WriteLine($"删除结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"删除失败: {result.Message}"); + + // 验证删除结果 + var getResult = await app.Get(new QueryDynamicEntityReq { TableName = TEST_TABLE, Id = id }); + Assert.That(getResult.Data, Is.Null, "数据应该已被删除"); + } + + /// + /// 测试批量删除 + /// + [Test] + public async Task TestDelete_Batch() + { + var app = _autofacServiceProvider.GetService(); + var ids = new[] { Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString() }; + + // 添加多条测试数据 + foreach (var id in ids) + { + await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"批量删除测试_{id.Substring(0, 8)}\",\"Age\":50}}" + }); + } + + // 批量删除 + var result = await app.Delete(new DelDynamicReq + { + TableName = TEST_TABLE, + Ids = ids + }); + + Console.WriteLine($"批量删除结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"批量删除失败: {result.Message}"); + + // 验证删除结果 + foreach (var id in ids) + { + var getResult = await app.Get(new QueryDynamicEntityReq { TableName = TEST_TABLE, Id = id }); + Assert.That(getResult.Data, Is.Null, $"数据 {id} 应该已被删除"); + } + } + + #endregion + + #region 完整 CRUD 流程测试 + + /// + /// 测试完整的 CRUD 流程 + /// + [Test] + public async Task TestCRUD_FullFlow() + { + var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + + Console.WriteLine("=== 开始完整 CRUD 流程测试 ==="); + + // 1. Create - 创建数据 + Console.WriteLine("\n1. 创建数据..."); + var addResult = await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"CRUD测试\",\"Age\":18}}" + }); + Console.WriteLine($"创建结果: {JsonHelper.Instance.Serialize(addResult)}"); + Assert.That(addResult.Code, Is.EqualTo(200), $"创建失败: {addResult.Message}"); + + // 2. Read - 读取数据 + Console.WriteLine("\n2. 读取数据..."); + var getResult = await app.Get(new QueryDynamicEntityReq + { + TableName = TEST_TABLE, + Id = id + }); + Console.WriteLine($"读取结果: {JsonHelper.Instance.Serialize(getResult)}"); + Assert.That(getResult.Code, Is.EqualTo(200), $"读取失败: {getResult.Message}"); + Assert.That(getResult.Data, Is.Not.Null, "数据不应为空"); + + // 3. Update - 更新数据 + Console.WriteLine("\n3. 更新数据..."); + var updateResult = await app.Update(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"CRUD测试_已更新\",\"Age\":19}}" + }); + Console.WriteLine($"更新结果: {JsonHelper.Instance.Serialize(updateResult)}"); + Assert.That(updateResult.Code, Is.EqualTo(200), $"更新失败: {updateResult.Message}"); + + // 验证更新 + var getResult2 = await app.Get(new QueryDynamicEntityReq { TableName = TEST_TABLE, Id = id }); + Console.WriteLine($"更新后数据: {JsonHelper.Instance.Serialize(getResult2)}"); + + // 4. Delete - 删除数据 + Console.WriteLine("\n4. 删除数据..."); + var deleteResult = await app.Delete(new DelDynamicReq + { + TableName = TEST_TABLE, + Ids = new[] { id } + }); + Console.WriteLine($"删除结果: {JsonHelper.Instance.Serialize(deleteResult)}"); + Assert.That(deleteResult.Code, Is.EqualTo(200), $"删除失败: {deleteResult.Message}"); + + // 验证删除 + var getResult3 = await app.Get(new QueryDynamicEntityReq { TableName = TEST_TABLE, Id = id }); + Assert.That(getResult3.Data, Is.Null, "数据应该已被删除"); + + Console.WriteLine("\n=== 完整 CRUD 流程测试完成 ==="); + } + + #endregion + + #region Invoke 方法测试 + + /// + /// 测试 Invoke 调用 - 获取父级用户 + /// + [Test] + public async Task TestInvoke_GetParent() { var app = _autofacServiceProvider.GetService(); - var obj = await app.Invoke(new InvokeDynamicReq { ServiceName = "UserManagerApp", MethodName = "GetParent", - Parameters = "{\"userid\":\"0ceff0f8-f848-440c-bc26-d8605ac858cd\"}" }); - Console.WriteLine(JsonHelper.Instance.Serialize(obj)); + var result = await app.Invoke(new InvokeDynamicReq + { + ServiceName = "UserManagerApp", + MethodName = "GetParent", + Parameters = "{\"userid\":\"0ceff0f8-f848-440c-bc26-d8605ac858cd\"}" + }); + + Console.WriteLine($"Invoke GetParent 结果: {JsonHelper.Instance.Serialize(result)}"); } + /// + /// 测试 Invoke 调用 - 加载用户列表 + /// [Test] - public async Task TestInvoke2() + public async Task TestInvoke_Load() { var app = _autofacServiceProvider.GetService(); - - var obj = await app.Invoke(new InvokeDynamicReq { - ServiceName = "UserManagerApp", - MethodName = "Load", - Parameters = "{\"request\":{\"page\":1,\"limit\":10,\"key\":\"dddd\"}}" - }); - Console.WriteLine(JsonHelper.Instance.Serialize(obj)); - - } + + var result = await app.Invoke(new InvokeDynamicReq + { + ServiceName = "UserManagerApp", + MethodName = "Load", + Parameters = "{\"request\":{\"page\":1,\"limit\":10,\"key\":\"\"}}" + }); + + Console.WriteLine($"Invoke Load 结果: {JsonHelper.Instance.Serialize(result)}"); + } + + /// + /// 测试 Invoke 调用 - 参数大小写混合 + /// + [Test] + public async Task TestInvoke_MixedCaseParameters() + { + var app = _autofacServiceProvider.GetService(); + + // 使用混合大小写的参数 + var result = await app.Invoke(new InvokeDynamicReq + { + ServiceName = "UserManagerApp", + MethodName = "Load", + Parameters = "{\"Request\":{\"Page\":1,\"Limit\":10,\"Key\":\"\"}}" + }); + + Console.WriteLine($"Invoke MixedCase 结果: {JsonHelper.Instance.Serialize(result)}"); + } + + #endregion + + #region 异常场景测试 + + /// + /// 测试不存在的表 + /// + [Test] + public async Task TestNonExistentTable() + { + var app = _autofacServiceProvider.GetService(); + + var result = await app.GetList(new QueryDynamicListReq + { + TableName = "non_existent_table_12345", + page = 1, + limit = 10 + }); + + Console.WriteLine($"查询不存在的表结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(500), "应该返回错误"); + Assert.That(result.Message, Does.Contain("表不存在"), "错误信息应包含'表不存在'"); + } + + /// + /// 测试更新不包含Id的数据 + /// + [Test] + public async Task TestUpdate_WithoutId() + { + var app = _autofacServiceProvider.GetService(); + + var result = await app.Update(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = "{\"Name\":\"没有Id的更新\",\"Age\":99}" + }); + + Console.WriteLine($"无Id更新结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(500), "应该返回错误"); + Assert.That(result.Message, Does.Contain("Id"), "错误信息应包含'Id'"); + } + + /// + /// 测试添加重复Id的数据 + /// + [Test] + public async Task TestAdd_DuplicateId() + { + var app = _autofacServiceProvider.GetService(); + var id = Guid.NewGuid().ToString(); + + // 第一次添加 + await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"第一次添加\",\"Age\":1}}" + }); + + // 第二次添加相同Id + var result = await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = $"{{\"Id\":\"{id}\",\"Name\":\"第二次添加\",\"Age\":2}}" + }); + + Console.WriteLine($"重复Id添加结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(500), "应该返回错误"); + Assert.That(result.Message, Does.Contain("Id已存在"), "错误信息应包含'Id已存在'"); + + // 清理测试数据 + await CleanupTestData(app, id); + } + + /// + /// 测试获取不存在的记录 + /// + [Test] + public async Task TestGet_NonExistent() + { + var app = _autofacServiceProvider.GetService(); + + var result = await app.Get(new QueryDynamicEntityReq + { + TableName = TEST_TABLE, + Id = "non_existent_id_12345" + }); + + Console.WriteLine($"获取不存在记录结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(500), "应该返回错误"); + Assert.That(result.Message, Does.Contain("未找到"), "错误信息应包含'未找到'"); + } + + #endregion + + #region 自动生成ID测试 + + /// + /// 测试添加数据时自动生成Id + /// + [Test] + public async Task TestAdd_AutoGenerateId() + { + var app = _autofacServiceProvider.GetService(); + + // 不传Id + var result = await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = "{\"Name\":\"自动生成Id测试\",\"Age\":33}" + }); + + Console.WriteLine($"自动生成Id结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"添加失败: {result.Message}"); + + // 查询并验证确实有数据被添加 + var listResult = await app.GetList(new QueryDynamicListReq + { + TableName = TEST_TABLE, + page = 1, + limit = 100, + key = "自动生成Id测试" + }); + + Console.WriteLine($"查询结果: {JsonHelper.Instance.Serialize(listResult)}"); + Assert.That(listResult.Count, Is.GreaterThan(0), "应该能查到数据"); + } + + /// + /// 测试添加数据时Id为空字符串,应自动生成 + /// + [Test] + public async Task TestAdd_EmptyId() + { + var app = _autofacServiceProvider.GetService(); + + // 传空Id + var result = await app.Add(new AddOrUpdateDynamicEntityReq + { + TableName = TEST_TABLE, + Obj = "{\"Id\":\"\",\"Name\":\"空Id测试\",\"Age\":34}" + }); + + Console.WriteLine($"空Id测试结果: {JsonHelper.Instance.Serialize(result)}"); + Assert.That(result.Code, Is.EqualTo(200), $"添加失败: {result.Message}"); + } + + #endregion + + #region 辅助方法 + + /// + /// 清理测试数据 + /// + private async Task CleanupTestData(DynamicApiApp app, string id) + { + try + { + await app.Delete(new DelDynamicReq + { + TableName = TEST_TABLE, + Ids = new[] { id } + }); + } + catch (Exception ex) + { + Console.WriteLine($"清理测试数据失败: {ex.Message}"); + } + } + + #endregion } }