using NUnit.Framework; using System; using Newtonsoft.Json.Linq; using UVC.Data; using UnityEngine; namespace UVC.Tests.Data { /// /// DataMapper 클래스의 테스트를 위한 테스트 클래스입니다. /// [TestFixture] public class DataMapperTests { /// /// 모든 테스트 메서드를 실행하는 메서드입니다. /// /// /// 이 메서드는 클래스의 모든 테스트 메서드를 순차적으로 호출하고 /// 각 테스트의 성공 또는 실패 여부를 로그로 출력합니다. /// public void TestAll() { Debug.Log("===== DataMapper 테스트 시작 ====="); RunTest(nameof(Map_StringProperty_MapsCorrectly), Map_StringProperty_MapsCorrectly); RunTest(nameof(Map_IntProperty_MapsCorrectly), Map_IntProperty_MapsCorrectly); RunTest(nameof(Map_DoubleProperty_MapsCorrectly), Map_DoubleProperty_MapsCorrectly); RunTest(nameof(Map_BoolProperty_MapsCorrectly), Map_BoolProperty_MapsCorrectly); RunTest(nameof(Map_DateTimeProperty_MapsCorrectly), Map_DateTimeProperty_MapsCorrectly); RunTest(nameof(Map_DataValueMapperProperty_MapsCorrectly), Map_DataValueMapperProperty_MapsCorrectly); RunTest(nameof(Map_DataValueMapperWithUnmappedValue_ReturnsOriginal), Map_DataValueMapperWithUnmappedValue_ReturnsOriginal); RunTest(nameof(Map_EnumProperty_MapsCorrectly), Map_EnumProperty_MapsCorrectly); RunTest(nameof(Map_AdditionalProperty_AddsToResult), Map_AdditionalProperty_AddsToResult); RunTest(nameof(Map_InvalidDateTimeString_ReturnsNull), Map_InvalidDateTimeString_ReturnsNull); RunTest(nameof(Map_ComplexObject_MapsAllProperties), Map_ComplexObject_MapsAllProperties); RunTest(nameof(Map_NestedObject_MapsCorrectly), Map_NestedObject_MapsCorrectly); RunTest(nameof(Map_ArrayMapping_MapsCorrectly), Map_ArrayMapping_MapsCorrectly); RunTest(nameof(Map_EmptyGuideArray_CopiesSourceArray), Map_EmptyGuideArray_CopiesSourceArray); RunTest(nameof(Map_ComplexNestedStructure_MapsCorrectly), Map_ComplexNestedStructure_MapsCorrectly); RunTest(nameof(Map_MixedArrayTypes_HandlesCorrectly), Map_MixedArrayTypes_HandlesCorrectly); 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}"); } } /// /// 문자열 타입 매핑 테스트 /// [Test] public void Map_StringProperty_MapsCorrectly() { // Arrange var guide = new JObject(); guide["Name"] = "홍길동"; var source = JObject.Parse(@"{ ""Name"": ""김철수"" }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("Name")); Assert.AreEqual("김철수", result["Name"].ToString()); } /// /// 정수 타입 매핑 테스트 /// [Test] public void Map_IntProperty_MapsCorrectly() { // Arrange var guide = new JObject(); guide["Age"] = 25; var source = JObject.Parse(@"{ ""Age"": 30 }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("Age")); Assert.AreEqual(30, result["Age"].ToObject()); } /// /// 부동소수점 타입 매핑 테스트 /// [Test] public void Map_DoubleProperty_MapsCorrectly() { // Arrange var guide = new JObject(); guide["Height"] = 175.5; var source = JObject.Parse(@"{ ""Height"": 180.5 }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("Height")); Assert.AreEqual(180.5, result["Height"].ToObject()); } /// /// Boolean 타입 매핑 테스트 /// [Test] public void Map_BoolProperty_MapsCorrectly() { // Arrange var guide = new JObject(); guide["IsActive"] = false; var source = JObject.Parse(@"{ ""IsActive"": true }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("IsActive")); Assert.IsTrue(result["IsActive"].ToObject()); } /// /// DateTime 타입 매핑 테스트 /// [Test] public void Map_DateTimeProperty_MapsCorrectly() { // Arrange var guide = new JObject(); guide["BirthDate"] = JToken.FromObject(DateTime.Now); var expectedDate = new DateTime(1990, 1, 1); var source = JObject.Parse(@"{ ""BirthDate"": ""1990-01-01T00:00:00.000"" }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("BirthDate")); Assert.AreEqual(expectedDate, result["BirthDate"].ToObject()); } /// /// DataValueMapper 타입 매핑 테스트 /// [Test] public void Map_DataValueMapperProperty_MapsCorrectly() { // Arrange var guide = new JObject(); var valueMapper = new DataValueMapper(); valueMapper["ON"] = "활성화"; valueMapper["OFF"] = "비활성화"; guide["Status"] = JToken.FromObject(valueMapper); var source = JObject.Parse(@"{ ""Status"": ""ON"" }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("Status")); Assert.AreEqual("활성화", result["Status"].ToString()); } /// /// DataValueMapper에 매핑되지 않는 값 처리 테스트 /// [Test] public void Map_DataValueMapperWithUnmappedValue_ReturnsOriginal() { // Arrange var guide = new JObject(); var valueMapper = new DataValueMapper(); valueMapper["ON"] = "활성화"; valueMapper["OFF"] = "비활성화"; guide["Status"] = JToken.FromObject(valueMapper); var source = JObject.Parse(@"{ ""Status"": ""UNKNOWN"" }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("Status")); Assert.AreEqual("UNKNOWN", result["Status"].ToString()); } /// /// 열거형 타입 매핑 테스트 /// [Test] public void Map_EnumProperty_MapsCorrectly() { // Arrange var guide = new JObject(); guide["Status"] = JToken.FromObject(UserStatus.Inactive); var source = JObject.Parse(@"{ ""Status"": ""Active"" }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("Status")); Assert.AreEqual(UserStatus.Active, result["Status"].ToObject()); } /// /// 타겟에 없는 추가 속성 매핑 테스트 /// [Test] public void Map_AdditionalProperty_AddsToResult() { // Arrange var guide = new JObject(); guide["Name"] = "홍길동"; var source = JObject.Parse(@"{ ""Name"": ""김철수"", ""Email"": ""kim@example.com"" }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("Email")); Assert.AreEqual("kim@example.com", result["Email"].ToString()); } /// /// 유효하지 않은 DateTime 문자열 매핑 테스트 /// [Test] public void Map_InvalidDateTimeString_ReturnsNull() { // Arrange var guide = new JObject(); guide["BirthDate"] = JToken.FromObject(DateTime.Now); var source = JObject.Parse(@"{ ""BirthDate"": ""InvalidDateTime"" }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("BirthDate")); Assert.AreEqual(JTokenType.Null, result["BirthDate"].Type); } /// /// 복합 객체 매핑 테스트 /// [Test] public void Map_ComplexObject_MapsAllProperties() { // Arrange var guide = new JObject(); guide["Id"] = 1; guide["Name"] = "홍길동"; guide["IsActive"] = false; guide["JoinDate"] = JToken.FromObject(DateTime.Now); guide["Height"] = 175.5; guide["Status"] = JToken.FromObject(UserStatus.Inactive); string json = @"{ ""Id"": 100, ""Name"": ""김철수"", ""IsActive"": true, ""JoinDate"": ""2023-01-01T00:00:00"", ""Height"": 180.0, ""Status"": ""Active"", ""Email"": ""kim@example.com"" }"; var source = JObject.Parse(json); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.AreEqual(7, result.Count); Assert.AreEqual(100, result["Id"].ToObject()); Assert.AreEqual("김철수", result["Name"].ToString()); Assert.IsTrue(result["IsActive"].ToObject()); Assert.AreEqual(new DateTime(2023, 1, 1), result["JoinDate"].ToObject()); Assert.AreEqual(180.0, result["Height"].ToObject()); Assert.AreEqual(UserStatus.Active, result["Status"].ToObject()); Assert.AreEqual("kim@example.com", result["Email"].ToString()); } /// /// 중첩된 객체 매핑 테스트 - 새로 추가 /// [Test] public void Map_NestedObject_MapsCorrectly() { // Arrange var guide = new JObject { ["User"] = new JObject { ["Name"] = "홍길동", ["Address"] = new JObject { ["City"] = "서울", ["ZipCode"] = "12345" } } }; var source = JObject.Parse(@"{ ""User"": { ""Name"": ""김철수"", ""Address"": { ""City"": ""부산"", ""ZipCode"": ""67890"", ""Country"": ""대한민국"" } } }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("User")); var user = result["User"] as JObject; Assert.IsNotNull(user); Assert.AreEqual("김철수", user["Name"].ToString()); var address = user["Address"] as JObject; Assert.IsNotNull(address); Assert.AreEqual("부산", address["City"].ToString()); Assert.AreEqual("67890", address["ZipCode"].ToString()); Assert.AreEqual("대한민국", address["Country"].ToString()); } /// /// 배열 매핑 테스트 - 새로 추가 /// [Test] public void Map_ArrayMapping_MapsCorrectly() { // Arrange var guide = new JObject { ["Contacts"] = new JArray { new JObject { ["Type"] = "mobile", ["Number"] = "010-0000-0000" } } }; var source = JObject.Parse(@"{ ""Contacts"": [ { ""Type"": ""mobile"", ""Number"": ""010-1234-5678"" }, { ""Type"": ""home"", ""Number"": ""02-123-4567"", ""Extension"": ""123"" } ] }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("Contacts")); var contacts = result["Contacts"] as JArray; Assert.IsNotNull(contacts); Assert.AreEqual(2, contacts.Count); var contact1 = contacts[0] as JObject; Assert.IsNotNull(contact1); Assert.AreEqual("mobile", contact1["Type"].ToString()); Assert.AreEqual("010-1234-5678", contact1["Number"].ToString()); var contact2 = contacts[1] as JObject; Assert.IsNotNull(contact2); Assert.AreEqual("home", contact2["Type"].ToString()); Assert.AreEqual("02-123-4567", contact2["Number"].ToString()); Assert.AreEqual("123", contact2["Extension"].ToString()); } /// /// 빈 가이드 배열 테스트 - 새로 추가 /// [Test] public void Map_EmptyGuideArray_CopiesSourceArray() { // Arrange var guide = new JObject { ["Tags"] = new JArray() }; var source = JObject.Parse(@"{ ""Tags"": [""개발"", ""테스트"", ""배포""] }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert Assert.IsTrue(result.ContainsKey("Tags")); var tags = result["Tags"] as JArray; Assert.IsNotNull(tags); Assert.AreEqual(3, tags.Count); Assert.AreEqual("개발", tags[0].ToString()); Assert.AreEqual("테스트", tags[1].ToString()); Assert.AreEqual("배포", tags[2].ToString()); } /// /// 복잡한 중첩 구조 매핑 테스트 - 새로 추가 /// [Test] public void Map_ComplexNestedStructure_MapsCorrectly() { // Arrange var guide = new JObject { ["Company"] = new JObject { ["Name"] = "회사명", ["Founded"] = JToken.FromObject(DateTime.Now), ["Departments"] = new JArray { new JObject { ["Name"] = "부서명", ["Employees"] = new JArray { new JObject { ["Name"] = "직원명", ["Age"] = 30, ["Status"] = JToken.FromObject(UserStatus.Active) } } } } } }; var source = JObject.Parse(@"{ ""Company"": { ""Name"": ""XYZ 주식회사"", ""Founded"": ""2000-01-01T00:00:00"", ""Departments"": [ { ""Name"": ""개발부"", ""Employees"": [ { ""Name"": ""김개발"", ""Age"": 35, ""Status"": ""Active"" }, { ""Name"": ""이테스트"", ""Age"": 28, ""Status"": ""Inactive"" } ] }, { ""Name"": ""마케팅부"", ""Employees"": [ { ""Name"": ""박마케팅"", ""Age"": 32, ""Status"": ""Active"" } ], ""Budget"": 500000 } ], ""Address"": ""서울시 강남구"" } }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert var company = result["Company"] as JObject; Assert.IsNotNull(company); Assert.AreEqual("XYZ 주식회사", company["Name"].ToString()); Assert.AreEqual(new DateTime(2000, 1, 1), company["Founded"].ToObject()); Assert.AreEqual("서울시 강남구", company["Address"].ToString()); var departments = company["Departments"] as JArray; Assert.IsNotNull(departments); Assert.AreEqual(2, departments.Count); var devDept = departments[0] as JObject; Assert.AreEqual("개발부", devDept["Name"].ToString()); var devEmployees = devDept["Employees"] as JArray; Assert.AreEqual(2, devEmployees.Count); Assert.AreEqual("김개발", devEmployees[0]["Name"].ToString()); Assert.AreEqual(35, devEmployees[0]["Age"].ToObject()); Assert.AreEqual(UserStatus.Active, devEmployees[0]["Status"].ToObject()); Assert.AreEqual("이테스트", devEmployees[1]["Name"].ToString()); Assert.AreEqual(UserStatus.Inactive, devEmployees[1]["Status"].ToObject()); var marketingDept = departments[1] as JObject; Assert.AreEqual("마케팅부", marketingDept["Name"].ToString()); Assert.AreEqual(500000, marketingDept["Budget"].ToObject()); var marketingEmployees = marketingDept["Employees"] as JArray; Assert.AreEqual(1, marketingEmployees.Count); Assert.AreEqual("박마케팅", marketingEmployees[0]["Name"].ToString()); } /// /// 다양한 형식의 배열 테스트 - 새로 추가 /// [Test] public void Map_MixedArrayTypes_HandlesCorrectly() { // Arrange var guide = new JObject { ["MixedArray"] = new JArray { "문자열", 123, true, new JObject { ["Key"] = "Value" } } }; var source = JObject.Parse(@"{ ""MixedArray"": [ ""테스트"", 456, false, { ""Key"": ""NewValue"", ""Extra"": ""ExtraValue"" }, [1, 2, 3] ] }"); var mapper = new DataMapper(source, guide); // Act var result = mapper.Map(); // Assert var mixedArray = result["MixedArray"] as JArray; Assert.IsNotNull(mixedArray); Assert.AreEqual(5, mixedArray.Count); Assert.AreEqual("테스트", mixedArray[0].ToString()); Assert.AreEqual(456, mixedArray[1].ToObject()); Assert.AreEqual(false, mixedArray[2].ToObject()); var objInArray = mixedArray[3] as JObject; Assert.IsNotNull(objInArray); Assert.AreEqual("NewValue", objInArray["Key"].ToString()); Assert.AreEqual("ExtraValue", objInArray["Extra"].ToString()); var nestedArray = mixedArray[4] as JArray; Assert.IsNotNull(nestedArray); Assert.AreEqual(3, nestedArray.Count); } } /// /// 테스트에 사용할 샘플 열거형 /// public enum UserStatus { Active, Inactive, Suspended } }