using Common.ExpandFun; namespace Common.Test; /// /// StringExpand 字符串扩展方法测试 /// 展示字符串相关的实用扩展方法 /// [TestClass] public class StringExpandTests { #region IsValidUrl 测试 /// /// 测试:有效的 HTTP URL /// [TestMethod] public void IsValidUrl_ValidHttpUrl_ReturnsTrue() { // Arrange var url = "http://www.example.com"; // Act var isValid = url.IsValidUrl(); // Assert Assert.IsTrue(isValid); } /// /// 测试:有效的 HTTPS URL /// [TestMethod] public void IsValidUrl_ValidHttpsUrl_ReturnsTrue() { // Arrange var url = "https://www.example.com/path/to/resource?query=value"; // Act var isValid = url.IsValidUrl(); // Assert Assert.IsTrue(isValid); } /// /// 测试:有效的 FTP URL /// [TestMethod] public void IsValidUrl_ValidFtpUrl_ReturnsTrue() { // Arrange var url = "ftp://ftp.example.com/file.txt"; // Act var isValid = url.IsValidUrl(); // Assert Assert.IsTrue(isValid); } /// /// 测试:无效的 URL /// [TestMethod] public void IsValidUrl_InvalidUrl_ReturnsFalse() { // Arrange var invalidUrls = new[] { "not a url", "example.com", // 缺少协议 "http://", // 不完整 "", // 空字符串 "://invalid" // 无效格式 }; // Act & Assert foreach (var url in invalidUrls) Assert.IsFalse(url.IsValidUrl(), $"'{url}' should be invalid"); } #endregion #region ToInt 和 TryToInt 测试 /// /// 测试:有效的整数字符串转换 /// [TestMethod] public void ToInt_ValidIntegerString_ReturnsInteger() { // Arrange & Act & Assert Assert.AreEqual(123, "123".ToInt()); Assert.AreEqual(-456, "-456".ToInt()); Assert.AreEqual(0, "0".ToInt()); } /// /// 测试:无效字符串返回默认值 /// [TestMethod] public void ToInt_InvalidString_ReturnsDefault() { // Arrange & Act & Assert Assert.AreEqual(0, "invalid".ToInt()); Assert.AreEqual(0, "12.34".ToInt()); Assert.AreEqual(999, "abc".ToInt(999)); } /// /// 测试:空字符串和 null 返回默认值 /// [TestMethod] public void ToInt_NullOrEmpty_ReturnsDefault() { // Arrange & Act & Assert Assert.AreEqual(0, ((string)null!).ToInt()); Assert.AreEqual(0, "".ToInt()); Assert.AreEqual(0, " ".ToInt()); Assert.AreEqual(100, ((string)null!).ToInt(100)); } /// /// 测试:TryToInt 成功转换 /// [TestMethod] public void TryToInt_ValidString_ReturnsValue() { // Arrange & Act var result = "42".TryToInt(); // Assert Assert.IsNotNull(result); Assert.AreEqual(42, result.Value); } /// /// 测试:TryToInt 转换失败返回 null /// [TestMethod] public void TryToInt_InvalidString_ReturnsNull() { // Arrange & Act var result1 = "invalid".TryToInt(); var result2 = ((string)null!).TryToInt(); var result3 = "".TryToInt(); // Assert Assert.IsNull(result1); Assert.IsNull(result2); Assert.IsNull(result3); } /// /// 测试:整数溢出 /// [TestMethod] public void ToInt_Overflow_ReturnsDefault() { // Arrange: int.MaxValue + 1 var overflowString = "2147483648"; // Act var result = overflowString.ToInt(-1); // Assert: 溢出应该返回默认值 Assert.AreEqual(-1, result); } #endregion #region ToDouble 和 TryToDouble 测试 /// /// 测试:有效的浮点数字符串转换 /// [TestMethod] public void ToDouble_ValidDoubleString_ReturnsDouble() { // Arrange & Act & Assert Assert.AreEqual(123.456, "123.456".ToDouble()); Assert.AreEqual(-789.12, "-789.12".ToDouble()); Assert.AreEqual(0.0, "0".ToDouble()); Assert.AreEqual(3.14, "3.14".ToDouble()); } /// /// 测试:整数字符串也能转换为 double /// [TestMethod] public void ToDouble_IntegerString_ReturnsDouble() { // Arrange & Act var result = "42".ToDouble(); // Assert Assert.AreEqual(42.0, result); } /// /// 测试:无效字符串返回默认值 /// [TestMethod] public void ToDouble_InvalidString_ReturnsDefault() { // Arrange & Act & Assert Assert.AreEqual(0.0, "invalid".ToDouble()); Assert.AreEqual(999.9, "abc".ToDouble(999.9)); } /// /// 测试:空字符串和 null 返回默认值 /// [TestMethod] public void ToDouble_NullOrEmpty_ReturnsDefault() { // Arrange & Act & Assert Assert.AreEqual(0.0, ((string)null!).ToDouble()); Assert.AreEqual(0.0, "".ToDouble()); Assert.AreEqual(0.0, " ".ToDouble()); Assert.AreEqual(100.5, ((string)null!).ToDouble(100.5)); } /// /// 测试:TryToDouble 成功转换 /// [TestMethod] public void TryToDouble_ValidString_ReturnsValue() { // Arrange & Act var result = "3.14159".TryToDouble(); // Assert Assert.IsNotNull(result); Assert.AreEqual(3.14159, result.Value); } /// /// 测试:TryToDouble 转换失败返回 null /// [TestMethod] public void TryToDouble_InvalidString_ReturnsNull() { // Arrange & Act var result1 = "invalid".TryToDouble(); var result2 = ((string)null!).TryToDouble(); var result3 = "".TryToDouble(); // Assert Assert.IsNull(result1); Assert.IsNull(result2); Assert.IsNull(result3); } /// /// 测试:科学计数法 /// [TestMethod] public void ToDouble_ScientificNotation_ConvertsCorrectly() { // Arrange & Act & Assert Assert.AreEqual(1.23e5, "1.23e5".ToDouble()); Assert.AreEqual(1.23e-5, "1.23e-5".ToDouble()); } #endregion #region 实际应用场景测试 /// /// 场景测试:解析配置文件值 /// [TestMethod] public void Scenario_ParseConfigurationValues() { // Arrange: 模拟从配置文件读取的字符串值 var config = new Dictionary { ["Port"] = "8080", ["Timeout"] = "30", ["MaxRetries"] = "invalid", // 无效值 ["Price"] = "99.99", ["Discount"] = "0.15" }; // Act: 解析配置值 var port = config["Port"].ToInt(80); // 默认 80 var timeout = config["Timeout"].ToInt(60); // 默认 60 var maxRetries = config["MaxRetries"].ToInt(3); // 无效值,使用默认 3 var price = config["Price"].ToDouble(0.0); var discount = config["Discount"].ToDouble(0.0); // Assert Assert.AreEqual(8080, port); Assert.AreEqual(30, timeout); Assert.AreEqual(3, maxRetries); // 使用了默认值 Assert.AreEqual(99.99, price); Assert.AreEqual(0.15, discount); } /// /// 场景测试:验证用户输入的 URL /// [TestMethod] public void Scenario_ValidateUserInputUrl() { // Arrange: 模拟用户输入 var userInputs = new[] { "https://www.google.com", "not a url", "ftp://files.example.com", "example.com" }; // Act: 验证 URL var validUrls = userInputs.Where(url => url.IsValidUrl()).ToList(); // Assert Assert.AreEqual(2, validUrls.Count); Assert.IsTrue(validUrls.Contains("https://www.google.com")); Assert.IsTrue(validUrls.Contains("ftp://files.example.com")); } /// /// 场景测试:安全地解析用户输入的数字 /// [TestMethod] public void Scenario_SafelyParseUserInput() { // Arrange: 模拟用户输入(可能无效) var userAgeInput = "25"; var userWeightInput = "invalid"; string? userHeightInput = null; // Act: 安全解析 var age = userAgeInput.TryToInt(); var weight = userWeightInput.TryToDouble(); var height = userHeightInput.TryToDouble(); // Assert Assert.IsNotNull(age); Assert.AreEqual(25, age.Value); Assert.IsNull(weight); // 无效输入 Assert.IsNull(height); // null 输入 // 使用默认值的版本 var ageWithDefault = userAgeInput.ToInt(18); var weightWithDefault = userWeightInput.ToDouble(70.0); var heightWithDefault = userHeightInput.ToDouble(170.0); Assert.AreEqual(25, ageWithDefault); Assert.AreEqual(70.0, weightWithDefault); // 使用默认值 Assert.AreEqual(170.0, heightWithDefault); // 使用默认值 } /// /// 场景测试:处理来自外部 API 的数据 /// [TestMethod] public void Scenario_ParseApiResponse() { // Arrange: 模拟 API 返回的字符串数据 var apiData = new { UserId = "12345", Score = "95.5", ProfileUrl = "https://api.example.com/users/12345", InvalidUrl = "not-a-url", MissingValue = (string)null! }; // Act: 解析数据 var userId = apiData.UserId.ToInt(); var score = apiData.Score.ToDouble(); var isValidProfileUrl = apiData.ProfileUrl.IsValidUrl(); var isValidInvalidUrl = apiData.InvalidUrl.IsValidUrl(); var missingValue = apiData.MissingValue.ToInt(-1); // Assert Assert.AreEqual(12345, userId); Assert.AreEqual(95.5, score); Assert.IsTrue(isValidProfileUrl); Assert.IsFalse(isValidInvalidUrl); Assert.AreEqual(-1, missingValue); } #endregion }