From cde234ddea3f0b25802aba0088bf9a3bfec4a736 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Fri, 17 Apr 2026 11:47:06 +0800 Subject: [PATCH] =?UTF-8?q?test(config):=20=E6=B7=BB=E5=8A=A0YAML=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=8A=A0=E8=BD=BD=E5=99=A8dependentSchemas=E7=BA=A6?= =?UTF-8?q?=E6=9D=9F=E5=8A=9F=E8=83=BD=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现YAML配置加载器对对象级dependentSchemas约束的运行时行为验证 - 添加dependentSchemas不满足时抛出异常的测试用例 - 添加触发字段缺席时不误触发dependentSchemas检查的测试用例 - 添加dependentSchemas满足时正常加载并保留额外字段的测试用例 - 添加非对象类型dependentSchemas声明时抛出异常的测试用例 - 添加触发字段未在同级properties中声明时的错误处理测试 - 添加dependentSchemas条件子schema非object类型时的验证测试 - 实现临时目录管理以避免不同测试场景间的数据污染 - 提供完整的测试辅助方法包括文件创建、schema构建等功能 --- .../YamlConfigLoaderDependentSchemasTests.cs | 290 ++++++++---------- 1 file changed, 125 insertions(+), 165 deletions(-) diff --git a/GFramework.Game.Tests/Config/YamlConfigLoaderDependentSchemasTests.cs b/GFramework.Game.Tests/Config/YamlConfigLoaderDependentSchemasTests.cs index e936db2d..66a1e1a9 100644 --- a/GFramework.Game.Tests/Config/YamlConfigLoaderDependentSchemasTests.cs +++ b/GFramework.Game.Tests/Config/YamlConfigLoaderDependentSchemasTests.cs @@ -10,6 +10,26 @@ namespace GFramework.Game.Tests.Config; [TestFixture] public sealed class YamlConfigLoaderDependentSchemasTests { + private const string DefaultRewardPropertiesJson = """ + { + "itemId": { "type": "string" }, + "itemCount": { "type": "integer" }, + "bonus": { "type": "integer" } + } + """; + + private const string DefaultDependentSchemasJson = """ + { + "itemId": { + "type": "object", + "required": ["itemCount"], + "properties": { + "itemCount": { "type": "integer" } + } + } + } + """; + private string? _rootPath; /// @@ -43,39 +63,13 @@ public sealed class YamlConfigLoaderDependentSchemasTests { CreateConfigFile( "monster/slime.yaml", - """ - id: 1 - reward: - itemId: potion - """); + BuildMonsterConfigYaml( + """ + itemId: potion + """)); CreateSchemaFile( "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "reward"], - "properties": { - "id": { "type": "integer" }, - "reward": { - "type": "object", - "properties": { - "itemId": { "type": "string" }, - "itemCount": { "type": "integer" }, - "bonus": { "type": "integer" } - }, - "dependentSchemas": { - "itemId": { - "type": "object", - "required": ["itemCount"], - "properties": { - "itemCount": { "type": "integer" } - } - } - } - } - } - } - """); + BuildMonsterSchema(DefaultRewardPropertiesJson, DefaultDependentSchemasJson)); var loader = CreateMonsterRewardLoader(); var registry = CreateRegistry(); @@ -101,39 +95,13 @@ public sealed class YamlConfigLoaderDependentSchemasTests { CreateConfigFile( "monster/slime.yaml", - """ - id: 1 - reward: - bonus: 2 - """); + BuildMonsterConfigYaml( + """ + bonus: 2 + """)); CreateSchemaFile( "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "reward"], - "properties": { - "id": { "type": "integer" }, - "reward": { - "type": "object", - "properties": { - "itemId": { "type": "string" }, - "itemCount": { "type": "integer" }, - "bonus": { "type": "integer" } - }, - "dependentSchemas": { - "itemId": { - "type": "object", - "required": ["itemCount"], - "properties": { - "itemCount": { "type": "integer" } - } - } - } - } - } - } - """); + BuildMonsterSchema(DefaultRewardPropertiesJson, DefaultDependentSchemasJson)); var loader = CreateMonsterRewardLoader(); var registry = CreateRegistry(); @@ -152,41 +120,15 @@ public sealed class YamlConfigLoaderDependentSchemasTests { CreateConfigFile( "monster/slime.yaml", - """ - id: 1 - reward: - itemId: potion - itemCount: 3 - bonus: 1 - """); + BuildMonsterConfigYaml( + """ + itemId: potion + itemCount: 3 + bonus: 1 + """)); CreateSchemaFile( "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "reward"], - "properties": { - "id": { "type": "integer" }, - "reward": { - "type": "object", - "properties": { - "itemId": { "type": "string" }, - "itemCount": { "type": "integer" }, - "bonus": { "type": "integer" } - }, - "dependentSchemas": { - "itemId": { - "type": "object", - "required": ["itemCount"], - "properties": { - "itemCount": { "type": "integer" } - } - } - } - } - } - } - """); + BuildMonsterSchema(DefaultRewardPropertiesJson, DefaultDependentSchemasJson)); var loader = CreateMonsterRewardLoader(); var registry = CreateRegistry(); @@ -212,30 +154,22 @@ public sealed class YamlConfigLoaderDependentSchemasTests { CreateConfigFile( "monster/slime.yaml", - """ - id: 1 - reward: - itemId: potion - """); + BuildMonsterConfigYaml( + """ + itemId: potion + """)); CreateSchemaFile( "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "reward"], - "properties": { - "id": { "type": "integer" }, - "reward": { - "type": "object", - "properties": { - "itemId": { "type": "string" }, - "itemCount": { "type": "integer" } - }, - "dependentSchemas": ["itemId"] + BuildMonsterSchema( + """ + { + "itemId": { "type": "string" }, + "itemCount": { "type": "integer" } } - } - } - """); + """, + """ + ["itemId"] + """)); var loader = CreateMonsterRewardLoader(); var registry = CreateRegistry(); @@ -260,36 +194,28 @@ public sealed class YamlConfigLoaderDependentSchemasTests { CreateConfigFile( "monster/slime.yaml", - """ - id: 1 - reward: - itemId: potion - """); + BuildMonsterConfigYaml( + """ + itemId: potion + """)); CreateSchemaFile( "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "reward"], - "properties": { - "id": { "type": "integer" }, - "reward": { - "type": "object", - "properties": { - "itemCount": { "type": "integer" } - }, - "dependentSchemas": { - "itemId": { - "type": "object", - "properties": { - "itemCount": { "type": "integer" } - } + BuildMonsterSchema( + """ + { + "itemCount": { "type": "integer" } + } + """, + """ + { + "itemId": { + "type": "object", + "properties": { + "itemCount": { "type": "integer" } } } } - } - } - """); + """)); var loader = CreateMonsterRewardLoader(); var registry = CreateRegistry(); @@ -314,34 +240,26 @@ public sealed class YamlConfigLoaderDependentSchemasTests { CreateConfigFile( "monster/slime.yaml", - """ - id: 1 - reward: - itemId: potion - """); + BuildMonsterConfigYaml( + """ + itemId: potion + """)); CreateSchemaFile( "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "reward"], - "properties": { - "id": { "type": "integer" }, - "reward": { - "type": "object", - "properties": { - "itemId": { "type": "string" } - }, - "dependentSchemas": { - "itemId": { - "type": "string", - "const": "potion" - } + BuildMonsterSchema( + """ + { + "itemId": { "type": "string" } + } + """, + """ + { + "itemId": { + "type": "string", + "const": "potion" } } - } - } - """); + """)); var loader = CreateMonsterRewardLoader(); var registry = CreateRegistry(); @@ -387,6 +305,48 @@ public sealed class YamlConfigLoaderDependentSchemasTests CreateConfigFile(relativePath, content); } + private static string BuildMonsterConfigYaml(string rewardYaml) + { + return $$""" + id: 1 + reward: + {{IndentLines(rewardYaml, 2)}} + """; + } + + private static string BuildMonsterSchema( + string rewardPropertiesJson, + string dependentSchemasJson) + { + return $$""" + { + "type": "object", + "required": ["id", "reward"], + "properties": { + "id": { "type": "integer" }, + "reward": { + "type": "object", + "properties": {{rewardPropertiesJson}}, + "dependentSchemas": {{dependentSchemasJson}} + } + } + } + """; + } + + private static string IndentLines(string text, int indentLevel) + { + var indentation = new string(' ', indentLevel); + var lines = text + .Trim() + .Split('\n', StringSplitOptions.None) + .Select(static line => line.TrimEnd('\r')); + + return string.Join( + Environment.NewLine, + lines.Select(line => $"{indentation}{line}")); + } + /// /// 创建用于对象 dependentSchemas 场景的加载器。 ///