using Common.Utils; using System.Net; namespace Common.Test; /// /// JsonHelper 测试 /// 展示 JSON 序列化和反序列化功能 /// [TestClass] public class JsonHelperTests { #region 基础序列化测试 /// /// 测试:序列化简单对象 /// [TestMethod] public void ToJson_SimpleObject_SerializesCorrectly() { // Arrange var person = new Person { Name = "John Doe", Age = 30, Email = "john@example.com" }; // Act var json = JsonHelper.ToJson(person); // Assert Assert.IsTrue(json.Contains("\"name\": \"John Doe\"")); // camelCase Assert.IsTrue(json.Contains("\"age\": 30")); Assert.IsTrue(json.Contains("\"email\": \"john@example.com\"")); } /// /// 测试:序列化使用 camelCase 命名策略 /// [TestMethod] public void ToJson_UsesCamelCase() { // Arrange var config = new AppConfig { AppName = "MyApp", MaxConnections = 100 }; // Act var json = JsonHelper.ToJson(config); // Assert: 属性名应该是 camelCase Assert.IsTrue(json.Contains("\"appName\"")); Assert.IsTrue(json.Contains("\"maxConnections\"")); Assert.IsFalse(json.Contains("\"AppName\"")); // 不应该是 PascalCase } /// /// 测试:序列化带格式化(缩进) /// [TestMethod] public void ToJson_WritesIndented() { // Arrange var person = new Person { Name = "Jane", Age = 25 }; // Act var json = JsonHelper.ToJson(person); // Assert: 应该包含换行符(表示有缩进) Assert.IsTrue(json.Contains("\n") || json.Contains("\r\n")); } #endregion #region 基础反序列化测试 /// /// 测试:反序列化简单对象 /// [TestMethod] public void FromJson_ValidJson_DeserializesCorrectly() { // Arrange var json = """ { "name": "Alice", "age": 28, "email": "alice@example.com" } """; // Act var person = JsonHelper.FromJson(json); // Assert Assert.IsNotNull(person); Assert.AreEqual("Alice", person.Name); Assert.AreEqual(28, person.Age); Assert.AreEqual("alice@example.com", person.Email); } /// /// 测试:反序列化 camelCase JSON /// [TestMethod] public void FromJson_CamelCaseJson_DeserializesCorrectly() { // Arrange: JSON 使用 camelCase var json = """ { "appName": "TestApp", "maxConnections": 50 } """; // Act var config = JsonHelper.FromJson(json); // Assert Assert.IsNotNull(config); Assert.AreEqual("TestApp", config.AppName); Assert.AreEqual(50, config.MaxConnections); } #endregion #region 特殊类型处理测试 /// /// 测试:序列化和反序列化枚举(使用字符串) /// [TestMethod] public void ToJson_Enum_SerializesAsString() { // Arrange var data = new DataWithEnum { Status = Status.Active, Priority = Priority.High }; // Act var json = JsonHelper.ToJson(data); // Assert: 枚举应该序列化为字符串(camelCase) Assert.IsTrue(json.Contains("\"active\"")); Assert.IsTrue(json.Contains("\"high\"")); Assert.IsFalse(json.Contains("0")); // 不应该是数字 Assert.IsFalse(json.Contains("1")); } /// /// 测试:反序列化枚举字符串 /// [TestMethod] public void FromJson_EnumString_DeserializesCorrectly() { // Arrange var json = """ { "status": "active", "priority": "low" } """; // Act var data = JsonHelper.FromJson(json); // Assert Assert.IsNotNull(data); Assert.AreEqual(Status.Active, data.Status); Assert.AreEqual(Priority.Low, data.Priority); } /// /// 测试:序列化 IPAddress /// [TestMethod] public void ToJson_IPAddress_SerializesCorrectly() { // Arrange var networkInfo = new NetworkInfo { ServerIp = IPAddress.Parse("192.168.1.1"), ClientIp = IPAddress.Parse("10.0.0.5") }; // Act var json = JsonHelper.ToJson(networkInfo); // Assert Assert.IsTrue(json.Contains("\"192.168.1.1\"")); Assert.IsTrue(json.Contains("\"10.0.0.5\"")); } /// /// 测试:反序列化 IPAddress /// [TestMethod] public void FromJson_IPAddress_DeserializesCorrectly() { // Arrange var json = """ { "serverIp": "192.168.1.1", "clientIp": "10.0.0.5" } """; // Act var networkInfo = JsonHelper.FromJson(json); // Assert Assert.IsNotNull(networkInfo); Assert.AreEqual(IPAddress.Parse("192.168.1.1"), networkInfo.ServerIp); Assert.AreEqual(IPAddress.Parse("10.0.0.5"), networkInfo.ClientIp); } /// /// 测试:IPv6 地址序列化和反序列化 /// [TestMethod] public void ToJson_IPv6Address_SerializesCorrectly() { // Arrange var networkInfo = new NetworkInfo { ServerIp = IPAddress.Parse("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), ClientIp = IPAddress.IPv6Loopback }; // Act var json = JsonHelper.ToJson(networkInfo); var deserialized = JsonHelper.FromJson(json); // Assert Assert.IsNotNull(deserialized); Assert.AreEqual(networkInfo.ServerIp, deserialized.ServerIp); Assert.AreEqual(IPAddress.IPv6Loopback, deserialized.ClientIp); } #endregion #region 复杂对象测试 /// /// 测试:序列化嵌套对象 /// [TestMethod] public void ToJson_NestedObject_SerializesCorrectly() { // Arrange var order = new Order { OrderId = "ORD-001", Customer = new Person { Name = "Bob", Age = 35, Email = "bob@example.com" }, Items = new List { new() { ProductName = "Laptop", Price = 999.99, Quantity = 1 }, new() { ProductName = "Mouse", Price = 29.99, Quantity = 2 } } }; // Act var json = JsonHelper.ToJson(order); var deserialized = JsonHelper.FromJson(json); // Assert Assert.IsNotNull(deserialized); Assert.AreEqual("ORD-001", deserialized.OrderId); Assert.AreEqual("Bob", deserialized.Customer?.Name); Assert.AreEqual(2, deserialized.Items?.Count); Assert.AreEqual("Laptop", deserialized.Items?[0].ProductName); Assert.AreEqual(999.99, deserialized.Items?[0].Price); } /// /// 测试:序列化集合 /// [TestMethod] public void ToJson_Collection_SerializesCorrectly() { // Arrange var people = new List { new() { Name = "Alice", Age = 30 }, new() { Name = "Bob", Age = 35 }, new() { Name = "Charlie", Age = 28 } }; // Act var json = JsonHelper.ToJson(people); var deserialized = JsonHelper.FromJson>(json); // Assert Assert.IsNotNull(deserialized); Assert.AreEqual(3, deserialized.Count); Assert.AreEqual("Alice", deserialized[0].Name); Assert.AreEqual("Bob", deserialized[1].Name); } #endregion #region 实际应用场景测试 /// /// 场景测试:配置文件序列化 /// 演示如何使用 JsonHelper 读写配置文件 /// [TestMethod] public void Scenario_SaveAndLoadConfiguration() { // Arrange: 创建配置对象 var originalConfig = new AppConfig { AppName = "MyApplication", MaxConnections = 100, Settings = new Dictionary { ["Theme"] = "Dark", ["Language"] = "en-US" } }; // Act: 序列化配置 var json = JsonHelper.ToJson(originalConfig); // 模拟保存到文件后再读取 var loadedConfig = JsonHelper.FromJson(json); // Assert: 验证配置正确加载 Assert.IsNotNull(loadedConfig); Assert.AreEqual(originalConfig.AppName, loadedConfig.AppName); Assert.AreEqual(originalConfig.MaxConnections, loadedConfig.MaxConnections); Assert.AreEqual("Dark", loadedConfig.Settings?["Theme"]); Assert.AreEqual("en-US", loadedConfig.Settings?["Language"]); } /// /// 场景测试:API 请求和响应 /// 演示如何序列化 API 数据 /// [TestMethod] public void Scenario_ApiRequestResponse() { // Arrange: 创建 API 请求 var request = new ApiRequest { Endpoint = "/api/users", Method = "POST", Headers = new Dictionary { ["Content-Type"] = "application/json", ["Authorization"] = "Bearer token123" }, Body = new Person { Name = "New User", Age = 25, Email = "newuser@example.com" } }; // Act: 序列化请求 var requestJson = JsonHelper.ToJson(request); // 模拟 API 调用后收到响应 var responseJson = """ { "success": true, "data": { "name": "New User", "age": 25, "email": "newuser@example.com" }, "message": "User created successfully" } """; var response = JsonHelper.FromJson>(responseJson); // Assert Assert.IsNotNull(response); Assert.IsTrue(response.Success); Assert.AreEqual("User created successfully", response.Message); Assert.IsNotNull(response.Data); Assert.AreEqual("New User", response.Data.Name); } /// /// 场景测试:网络配置持久化 /// 演示如何序列化包含 IPAddress 的复杂对象 /// [TestMethod] public void Scenario_NetworkConfigurationPersistence() { // Arrange: 创建网络配置 var networkConfig = new NetworkConfig { ServerIp = IPAddress.Parse("192.168.1.100"), DnsServers = new List { IPAddress.Parse("8.8.8.8"), IPAddress.Parse("8.8.4.4") }, Gateway = IPAddress.Parse("192.168.1.1") }; // Act: 序列化并反序列化 var json = JsonHelper.ToJson(networkConfig); var loaded = JsonHelper.FromJson(json); // Assert Assert.IsNotNull(loaded); Assert.AreEqual(networkConfig.ServerIp, loaded.ServerIp); Assert.AreEqual(2, loaded.DnsServers?.Count); Assert.AreEqual(IPAddress.Parse("8.8.8.8"), loaded.DnsServers?[0]); Assert.AreEqual(networkConfig.Gateway, loaded.Gateway); } #endregion #region 测试辅助类型 private class Person { public string Name { get; set; } = ""; public int Age { get; set; } public string? Email { get; set; } } private class AppConfig { public string AppName { get; set; } = ""; public int MaxConnections { get; set; } public Dictionary? Settings { get; set; } } private enum Status { Inactive = 0, Active = 1, Suspended = 2 } private enum Priority { Low = 0, Medium = 1, High = 2 } private class DataWithEnum { public Status Status { get; set; } public Priority Priority { get; set; } } private class NetworkInfo { public IPAddress? ServerIp { get; set; } public IPAddress? ClientIp { get; set; } } private class Order { public string OrderId { get; set; } = ""; public Person? Customer { get; set; } public List? Items { get; set; } } private class OrderItem { public string ProductName { get; set; } = ""; public double Price { get; set; } public int Quantity { get; set; } } private class ApiRequest { public string Endpoint { get; set; } = ""; public string Method { get; set; } = ""; public Dictionary? Headers { get; set; } public object? Body { get; set; } } private class ApiResponse { public bool Success { get; set; } public T? Data { get; set; } public string Message { get; set; } = ""; } private class NetworkConfig { public IPAddress? ServerIp { get; set; } public List? DnsServers { get; set; } public IPAddress? Gateway { get; set; } } #endregion }