510 lines
14 KiB
C#
510 lines
14 KiB
C#
using Common.Utils;
|
|
using System.Net;
|
|
|
|
namespace Common.Test;
|
|
|
|
/// <summary>
|
|
/// JsonHelper 测试
|
|
/// 展示 JSON 序列化和反序列化功能
|
|
/// </summary>
|
|
[TestClass]
|
|
public class JsonHelperTests
|
|
{
|
|
#region 基础序列化测试
|
|
|
|
/// <summary>
|
|
/// 测试:序列化简单对象
|
|
/// </summary>
|
|
[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\""));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试:序列化使用 camelCase 命名策略
|
|
/// </summary>
|
|
[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
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试:序列化带格式化(缩进)
|
|
/// </summary>
|
|
[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 基础反序列化测试
|
|
|
|
/// <summary>
|
|
/// 测试:反序列化简单对象
|
|
/// </summary>
|
|
[TestMethod]
|
|
public void FromJson_ValidJson_DeserializesCorrectly()
|
|
{
|
|
// Arrange
|
|
var json = """
|
|
{
|
|
"name": "Alice",
|
|
"age": 28,
|
|
"email": "alice@example.com"
|
|
}
|
|
""";
|
|
|
|
// Act
|
|
var person = JsonHelper.FromJson<Person>(json);
|
|
|
|
// Assert
|
|
Assert.IsNotNull(person);
|
|
Assert.AreEqual("Alice", person.Name);
|
|
Assert.AreEqual(28, person.Age);
|
|
Assert.AreEqual("alice@example.com", person.Email);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试:反序列化 camelCase JSON
|
|
/// </summary>
|
|
[TestMethod]
|
|
public void FromJson_CamelCaseJson_DeserializesCorrectly()
|
|
{
|
|
// Arrange: JSON 使用 camelCase
|
|
var json = """
|
|
{
|
|
"appName": "TestApp",
|
|
"maxConnections": 50
|
|
}
|
|
""";
|
|
|
|
// Act
|
|
var config = JsonHelper.FromJson<AppConfig>(json);
|
|
|
|
// Assert
|
|
Assert.IsNotNull(config);
|
|
Assert.AreEqual("TestApp", config.AppName);
|
|
Assert.AreEqual(50, config.MaxConnections);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 特殊类型处理测试
|
|
|
|
/// <summary>
|
|
/// 测试:序列化和反序列化枚举(使用字符串)
|
|
/// </summary>
|
|
[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"));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试:反序列化枚举字符串
|
|
/// </summary>
|
|
[TestMethod]
|
|
public void FromJson_EnumString_DeserializesCorrectly()
|
|
{
|
|
// Arrange
|
|
var json = """
|
|
{
|
|
"status": "active",
|
|
"priority": "low"
|
|
}
|
|
""";
|
|
|
|
// Act
|
|
var data = JsonHelper.FromJson<DataWithEnum>(json);
|
|
|
|
// Assert
|
|
Assert.IsNotNull(data);
|
|
Assert.AreEqual(Status.Active, data.Status);
|
|
Assert.AreEqual(Priority.Low, data.Priority);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试:序列化 IPAddress
|
|
/// </summary>
|
|
[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\""));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试:反序列化 IPAddress
|
|
/// </summary>
|
|
[TestMethod]
|
|
public void FromJson_IPAddress_DeserializesCorrectly()
|
|
{
|
|
// Arrange
|
|
var json = """
|
|
{
|
|
"serverIp": "192.168.1.1",
|
|
"clientIp": "10.0.0.5"
|
|
}
|
|
""";
|
|
|
|
// Act
|
|
var networkInfo = JsonHelper.FromJson<NetworkInfo>(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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试:IPv6 地址序列化和反序列化
|
|
/// </summary>
|
|
[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<NetworkInfo>(json);
|
|
|
|
// Assert
|
|
Assert.IsNotNull(deserialized);
|
|
Assert.AreEqual(networkInfo.ServerIp, deserialized.ServerIp);
|
|
Assert.AreEqual(IPAddress.IPv6Loopback, deserialized.ClientIp);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 复杂对象测试
|
|
|
|
/// <summary>
|
|
/// 测试:序列化嵌套对象
|
|
/// </summary>
|
|
[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<OrderItem>
|
|
{
|
|
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<Order>(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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试:序列化集合
|
|
/// </summary>
|
|
[TestMethod]
|
|
public void ToJson_Collection_SerializesCorrectly()
|
|
{
|
|
// Arrange
|
|
var people = new List<Person>
|
|
{
|
|
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<List<Person>>(json);
|
|
|
|
// Assert
|
|
Assert.IsNotNull(deserialized);
|
|
Assert.AreEqual(3, deserialized.Count);
|
|
Assert.AreEqual("Alice", deserialized[0].Name);
|
|
Assert.AreEqual("Bob", deserialized[1].Name);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 实际应用场景测试
|
|
|
|
/// <summary>
|
|
/// 场景测试:配置文件序列化
|
|
/// 演示如何使用 JsonHelper 读写配置文件
|
|
/// </summary>
|
|
[TestMethod]
|
|
public void Scenario_SaveAndLoadConfiguration()
|
|
{
|
|
// Arrange: 创建配置对象
|
|
var originalConfig = new AppConfig
|
|
{
|
|
AppName = "MyApplication",
|
|
MaxConnections = 100,
|
|
Settings = new Dictionary<string, string>
|
|
{
|
|
["Theme"] = "Dark",
|
|
["Language"] = "en-US"
|
|
}
|
|
};
|
|
|
|
// Act: 序列化配置
|
|
var json = JsonHelper.ToJson(originalConfig);
|
|
|
|
// 模拟保存到文件后再读取
|
|
var loadedConfig = JsonHelper.FromJson<AppConfig>(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"]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 场景测试:API 请求和响应
|
|
/// 演示如何序列化 API 数据
|
|
/// </summary>
|
|
[TestMethod]
|
|
public void Scenario_ApiRequestResponse()
|
|
{
|
|
// Arrange: 创建 API 请求
|
|
var request = new ApiRequest
|
|
{
|
|
Endpoint = "/api/users",
|
|
Method = "POST",
|
|
Headers = new Dictionary<string, string>
|
|
{
|
|
["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<ApiResponse<Person>>(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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 场景测试:网络配置持久化
|
|
/// 演示如何序列化包含 IPAddress 的复杂对象
|
|
/// </summary>
|
|
[TestMethod]
|
|
public void Scenario_NetworkConfigurationPersistence()
|
|
{
|
|
// Arrange: 创建网络配置
|
|
var networkConfig = new NetworkConfig
|
|
{
|
|
ServerIp = IPAddress.Parse("192.168.1.100"),
|
|
DnsServers = new List<IPAddress>
|
|
{
|
|
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<NetworkConfig>(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<string, string>? 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<OrderItem>? 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<string, string>? Headers { get; set; }
|
|
public object? Body { get; set; }
|
|
}
|
|
|
|
private class ApiResponse<T>
|
|
{
|
|
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<IPAddress>? DnsServers { get; set; }
|
|
public IPAddress? Gateway { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
} |