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
}