#nullable enable using Newtonsoft.Json.Linq; using NUnit.Framework; using System; using System.Linq; using UnityEngine; using UVC.Data.Core; namespace UVC.Tests.Data { [TestFixture] public class DataObjectTests { /// /// 모든 테스트 메서드를 실행하는 메서드입니다. /// /// /// 이 메서드는 클래스의 모든 테스트 메서드를 순차적으로 호출하고 /// 각 테스트의 성공 또는 실패 여부를 로그로 출력합니다. /// public void TestAll() { Debug.Log("===== DataMapper 테스트 시작 ====="); SetUp(); RunTest(nameof(UpdateDifferent_WhenCalled_UpdatesAndTracksChanges), UpdateDifferent_WhenCalled_UpdatesAndTracksChanges); SetUp(); RunTest(nameof(Indexer_WhenPropertyIsSet_TracksChange), Indexer_WhenPropertyIsSet_TracksChange); SetUp(); RunTest(nameof(Indexer_WhenNewPropertyIsAdded_TracksAsChange), Indexer_WhenNewPropertyIsAdded_TracksAsChange); SetUp(); RunTest(nameof(GetUpdatedObject_WhenCalledAfterChanges_ReturnsOnlyUpdatedProperties), GetUpdatedObject_WhenCalledAfterChanges_ReturnsOnlyUpdatedProperties); SetUp(); RunTest(nameof(MarkAllAsUpdated_WhenCalled_MarksAllPropertiesAsChanged), MarkAllAsUpdated_WhenCalled_MarksAllPropertiesAsChanged); SetUp(); RunTest(nameof(Remove_WhenCalled_RemovesPropertyAndChangeTracking), Remove_WhenCalled_RemovesPropertyAndChangeTracking); SetUp(); RunTest(nameof(GetTypeMethods_ReturnCorrectTypes), GetTypeMethods_ReturnCorrectTypes); SetUp(); RunTest(nameof(Constructor_FromJObject_CreatesCorrectObject), Constructor_FromJObject_CreatesCorrectObject); SetUp(); RunTest(nameof(IdProperty_ReturnsCorrectId), IdProperty_ReturnsCorrectId); SetUp(); RunTest(nameof(KeyOrder_IsPreservedByInsertion), KeyOrder_IsPreservedByInsertion); SetUp(); RunTest(nameof(DataObjectPool_GetAndReturn_WorksCorrectly), DataObjectPool_GetAndReturn_WorksCorrectly); Debug.Log("===== DataMapper 테스트 완료 ====="); } /// /// 단일 테스트 메서드를 실행하고 결과를 로그로 출력합니다. /// /// 테스트 메서드 이름 /// 실행할 테스트 메서드 private void RunTest(string testName, Action testAction) { try { Debug.Log($"테스트 시작: {testName}"); testAction(); Debug.Log($"테스트 성공: {testName}"); } catch (Exception ex) { Debug.LogError($"테스트 실패: {testName}\n{ex.Message}\n{ex.StackTrace}"); } } private DataObject _dataObject = new DataObject(); [SetUp] public void SetUp() { // 각 테스트가 실행되기 전에 DataObject를 초기화합니다. _dataObject = new DataObject { { "Id", 1 }, { "name", "Test" }, { "value", 100.5f }, { "isActive", true } }; // 초기 상태에서는 변경된 속성이 없어야 합니다. _dataObject.ClearChangedProperties(); // 변경 목록 초기화 } [Test] public void UpdateDifferent_WhenCalled_UpdatesAndTracksChanges() { // Arrange var otherDataObject = new DataObject { { "Id", 1 }, // 동일한 값 { "name", "Updated Test" }, // 변경된 값 { "newValue", "new" } // 새로 추가된 값 }; // Act _dataObject.UpdateDifferent(otherDataObject, true); // Assert Assert.AreEqual("Updated Test", _dataObject["name"]); Assert.AreEqual("new", _dataObject["newValue"]); Assert.AreEqual(2, _dataObject.UpdatedCount); Assert.Contains("name", _dataObject.ChangedProperies.ToList()); Assert.Contains("newValue", _dataObject.ChangedProperies.ToList()); } [Test] public void Indexer_WhenPropertyIsSet_TracksChange() { // Act _dataObject["name"] = "New Name"; // Assert Assert.AreEqual(1, _dataObject.UpdatedCount); Assert.Contains("name", _dataObject.ChangedProperies.ToList()); } [Test] public void Indexer_WhenNewPropertyIsAdded_TracksAsChange() { // Act _dataObject["newKey"] = "newValue"; // Assert Assert.AreEqual(1, _dataObject.UpdatedCount, "새로 추가된 속성은 변경으로 간주되어야 합니다."); Assert.IsTrue(_dataObject.ChangedProperies.Contains("newKey")); } [Test] public void GetUpdatedObject_WhenCalledAfterChanges_ReturnsOnlyUpdatedProperties() { // Arrange _dataObject["name"] = "Updated Name"; _dataObject["value"] = 200.0f; // Act var updatedObject = _dataObject.GetUpdatedObject() as DataObject; // Assert Assert.IsNotNull(updatedObject); Assert.AreEqual(2, updatedObject.Count); Assert.AreEqual("Updated Name", updatedObject["name"]); Assert.AreEqual(200.0f, updatedObject["value"]); } [Test] public void MarkAllAsUpdated_WhenCalled_MarksAllPropertiesAsChanged() { // Act _dataObject.MarkAllAsUpdated(); // Assert Assert.AreEqual(_dataObject.Count, _dataObject.UpdatedCount); CollectionAssert.AreEquivalent(_dataObject.Keys, _dataObject.ChangedProperies.ToList()); } [Test] public void Remove_WhenCalled_RemovesPropertyAndChangeTracking() { // Arrange _dataObject["name"] = "A new name to be removed"; Assert.Contains("name", _dataObject.ChangedProperies.ToList()); // Act bool result = _dataObject.Remove("name"); // Assert Assert.IsTrue(result); Assert.IsFalse(_dataObject.ContainsKey("name")); Assert.IsFalse(_dataObject.ChangedProperies.Contains("name")); } [Test] public void GetTypeMethods_ReturnCorrectTypes() { // Assert Assert.AreEqual(1, _dataObject.GetInt("Id")); Assert.AreEqual("Test", _dataObject.GetString("name")); Assert.AreEqual(100.5f, _dataObject.GetFloat("value")); Assert.IsTrue(_dataObject.GetBool("isActive")); } [Test] public void Constructor_FromJObject_CreatesCorrectObject() { // Arrange var jObject = new JObject { { "Id", 10 }, { "user", "jobject_user" } }; // Act var dataObject = new DataObject(jObject); // Assert Assert.AreEqual(10, dataObject.GetInt("Id")); Assert.AreEqual("jobject_user", dataObject.GetString("user")); Assert.AreEqual(0, dataObject.UpdatedCount, "생성자 호출 시에는 변경 추적을 하지 않아야 합니다."); } [Test] public void IdProperty_ReturnsCorrectId() { // Arrange _dataObject.IdKey = "Id"; // Act & Assert Assert.AreEqual("1", _dataObject.Id); // Arrange var noIdKeyObject = new DataObject { { "name", "Test" }, { "value", 100 } }; // Act & Assert // IdKey가 설정되지 않은 경우 첫 번째 항목의 값을 Id로 사용해야 합니다. Assert.AreEqual("Test", noIdKeyObject.Id); } [Test] public void KeyOrder_IsPreservedByInsertion() { // Arrange var orderedDataObject = new DataObject(); // Act orderedDataObject.Add("first", 1); orderedDataObject.Add("second", 2); orderedDataObject.Add("third", 3); // Assert var keys = orderedDataObject.Keys.ToList(); Assert.AreEqual("first", keys[0]); Assert.AreEqual("second", keys[1]); Assert.AreEqual("third", keys[2]); } [Test] public void DataObjectPool_GetAndReturn_WorksCorrectly() { // Act var obj = DataObjectPool.Get(); obj["test"] = "value"; // Assert Assert.IsNotNull(obj); Assert.AreEqual(1, obj.Count); // Act DataObjectPool.Return(obj); var retrievedObj = DataObjectPool.Get(); // Assert // 풀에서 다시 가져온 객체는 비어 있어야 합니다. Assert.AreEqual(0, retrievedObj.Count); } } }