Files
Workspace/Assets/Modules/ShrinkDataSaver/Tests/ShrinkSettingsTests.cs
T
cneicy d74c2f08ca feat(packages): 内置 SDK 包并完善 ContextLoader 集成
- 将 ShrinkEventBus、ShrinkDataSaver 及其 EventBus 集成从 gitlink 转为仓库直接维护的完整 UPM 包,补齐运行时、编辑器工具、测试与文档
- 新增 Command 和 Network 的 App 集成组件,支持 ContextLoader 服务发布、可逆注销及 Network Loopback 生命周期管理
- 更新 Starter 与演示组合逻辑,缺失模块时可注册、已有兼容安装器时可覆盖,并补充宿主启动断言
- 升级内部包依赖与 Shared CodeGen 包定义,放宽 Integration.App 包的 Git 忽略规则
- 将独立服务器生成器改为基于已编译程序集的语义扫描,支持 partial、复杂泛型、命名冲突检测及模板 SHA-256 覆写保护
- 新增 Network 语义扫描、模板保护和 App 组件生命周期测试
- 新增真实 UPM 消费工程验证脚本,校验内部版本一致性、程序集加载及 EditMode 测试
- 重构当前架构文档并归档已完成的 Cordis 迁移与旧代码地图
2026-08-18 18:06:34 +08:00

213 lines
6.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace ShrinkDataSaver.Tests
{
[TestFixture]
public class ShrinkSettingsTests
{
private MockStorageProvider _storage;
private ShrinkDataSaverSettings _settings;
[SetUp]
public void SetUp()
{
_storage = new MockStorageProvider();
_settings = ScriptableObject.CreateInstance<ShrinkDataSaverSettings>();
ShrinkDataSaverSettings.Instance = _settings;
ShrinkSettings.ResetForTesting();
ShrinkSettings.Initialize(_storage, "settings.json");
}
[TearDown]
public void TearDown()
{
ShrinkSettings.ResetForTesting();
if (_settings != null) Object.DestroyImmediate(_settings);
}
// ── Get / Set ──
[Test]
public void Set_Get_String()
{
ShrinkSettings.Set("name", "Alice");
Assert.AreEqual("Alice", ShrinkSettings.Get<string>("name"));
}
[Test]
public void Set_Get_Int()
{
ShrinkSettings.Set("score", 42);
Assert.AreEqual(42, ShrinkSettings.Get<int>("score"));
}
[Test]
public void Set_Get_Float()
{
ShrinkSettings.Set("volume", 0.75f);
Assert.AreEqual(0.75f, ShrinkSettings.Get<float>("volume"), 0.001f);
}
[Test]
public void Set_Get_Bool()
{
ShrinkSettings.Set("muted", true);
Assert.IsTrue(ShrinkSettings.Get<bool>("muted"));
}
[Test]
public void Set_Get_ComplexObject()
{
var data = new Dictionary<string, int> { { "a", 1 }, { "b", 2 } };
ShrinkSettings.Set("map", data);
var restored = ShrinkSettings.Get<Dictionary<string, int>>("map");
Assert.AreEqual(1, restored["a"]);
Assert.AreEqual(2, restored["b"]);
}
[Test]
public void Get_NonExistentKey_ReturnsDefault()
{
Assert.AreEqual(0, ShrinkSettings.Get<int>("missing"));
Assert.IsNull(ShrinkSettings.Get<string>("missing"));
Assert.AreEqual(99, ShrinkSettings.Get("missing", 99));
}
// ── Has / Remove ──
[Test]
public void Has_ExistingKey_ReturnsTrue()
{
ShrinkSettings.Set("key", "value");
Assert.IsTrue(ShrinkSettings.Has("key"));
}
[Test]
public void Has_NonExistentKey_ReturnsFalse()
{
Assert.IsFalse(ShrinkSettings.Has("ghost"));
}
[Test]
public void Remove_ExistingKey()
{
ShrinkSettings.Set("temp", 123);
Assert.IsTrue(ShrinkSettings.Has("temp"));
ShrinkSettings.Remove("temp");
Assert.IsFalse(ShrinkSettings.Has("temp"));
}
[Test]
public void Remove_NonExistentKey_NoError()
{
Assert.DoesNotThrow(() => ShrinkSettings.Remove("ghost"));
}
// ── GetAllRaw ──
[Test]
public void GetAllRaw_ReturnsAllSettings()
{
ShrinkSettings.Set("a", 1);
ShrinkSettings.Set("b", "two");
ShrinkSettings.Set("c", true);
var all = ShrinkSettings.GetAllRaw();
Assert.AreEqual(3, all.Count);
Assert.IsTrue(all.ContainsKey("a"));
Assert.IsTrue(all.ContainsKey("b"));
Assert.IsTrue(all.ContainsKey("c"));
}
// ── 事件 ──
[Test]
public void OnChanged_FiredOnSet()
{
string receivedKey = null;
object receivedValue = null;
ShrinkSettings.OnChanged += (k, v) => { receivedKey = k; receivedValue = v; };
ShrinkSettings.Set("volume", 0.5f);
Assert.AreEqual("volume", receivedKey);
}
[Test]
public void OnChanged_FiredOnRemove()
{
ShrinkSettings.Set("temp", "data");
string removedKey = null;
ShrinkSettings.OnChanged += (k, v) => { removedKey = k; };
ShrinkSettings.Remove("temp");
Assert.AreEqual("temp", removedKey);
}
// ── 持久化 ──
[UnityTest]
public IEnumerator SaveAsync_LoadAsync_RoundTrip() => UniTask.ToCoroutine(async () =>
{
ShrinkSettings.Set("persist_str", "hello");
ShrinkSettings.Set("persist_int", 42);
await ShrinkSettings.SaveAsync();
// 重置内存数据后重新加载
ShrinkSettings.ResetForTesting();
ShrinkSettings.Initialize(_storage, "settings.json");
await ShrinkSettings.LoadAsync();
Assert.AreEqual("hello", ShrinkSettings.Get<string>("persist_str"));
Assert.AreEqual(42, ShrinkSettings.Get<int>("persist_int"));
});
[UnityTest]
public IEnumerator LoadAsync_EmptyStorage_GivesCleanState() => UniTask.ToCoroutine(async () =>
{
await ShrinkSettings.LoadAsync();
Assert.AreEqual(0, ShrinkSettings.GetAllRaw().Count);
});
[UnityTest]
public IEnumerator LoadAsync_FallsBackToBackup_WhenPrimaryCorrupted() => UniTask.ToCoroutine(async () =>
{
ShrinkSettings.Set("lang", "zh_cn");
await ShrinkSettings.SaveAsync();
var backupBytes = await _storage.ReadAsync("settings.json");
await _storage.WriteAsync("settings.json.bak1", backupBytes);
// 用无法解析的字节模拟主文件损坏:结构合法但字段不符的 JSON 无法与“合法空设置”区分
await _storage.WriteAsync("settings.json", System.Text.Encoding.UTF8.GetBytes("{ \"lang\": \"zh_cn\" , broken"));
ShrinkSettings.ResetForTesting();
ShrinkSettings.Initialize(_storage, "settings.json");
await ShrinkSettings.LoadAsync();
Assert.AreEqual("zh_cn", ShrinkSettings.Get<string>("lang"));
var repairedPrimary = await _storage.ReadAsync("settings.json");
CollectionAssert.AreEqual(backupBytes, repairedPrimary);
});
// ── Overwrite ──
[Test]
public void Set_OverwriteExistingKey()
{
ShrinkSettings.Set("key", "first");
ShrinkSettings.Set("key", "second");
Assert.AreEqual("second", ShrinkSettings.Get<string>("key"));
}
}
}