using Common.Utils; namespace Common.Test; /// /// ValidationHelper 验证工具测试 /// 展示各种数据验证功能和 Result 模式集成 /// [TestClass] public class ValidationHelperTests { #region 邮箱验证测试 [TestMethod] public void IsValidEmail_ValidEmails_ReturnsTrue() { // Arrange var validEmails = new[] { "test@example.com", "user.name@example.com", "user+tag@example.co.uk", "test123@test-domain.com" }; // Act & Assert foreach (var email in validEmails) Assert.IsTrue(ValidationHelper.IsValidEmail(email), $"Failed for: {email}"); } [TestMethod] public void IsValidEmail_InvalidEmails_ReturnsFalse() { // Arrange var invalidEmails = new[] { "", "notanemail", "@example.com", "user@", "user @example.com", "user@.com" }; // Act & Assert foreach (var email in invalidEmails) Assert.IsFalse(ValidationHelper.IsValidEmail(email), $"Should fail for: {email}"); } [TestMethod] public void ValidateEmail_ValidEmail_ReturnsSuccess() { // Arrange var email = "test@example.com"; // Act var result = ValidationHelper.ValidateEmail(email); // Assert Assert.IsTrue(result.IsSuccess); Assert.AreEqual(email, result.Value); } [TestMethod] public void ValidateEmail_InvalidEmail_ReturnsFailure() { // Arrange var email = "invalid-email"; // Act var result = ValidationHelper.ValidateEmail(email); // Assert Assert.IsTrue(result.IsFailure); Assert.IsTrue(result.ErrorMessage.Contains("格式无效")); } #endregion #region 手机号验证测试 [TestMethod] public void IsValidChinaMobile_ValidMobiles_ReturnsTrue() { // Arrange var validMobiles = new[] { "13812345678", "15912345678", "18612345678", "19912345678" }; // Act & Assert foreach (var mobile in validMobiles) Assert.IsTrue(ValidationHelper.IsValidChinaMobile(mobile), $"Failed for: {mobile}"); } [TestMethod] public void IsValidChinaMobile_InvalidMobiles_ReturnsFalse() { // Arrange var invalidMobiles = new[] { "", "1234567890", // 10 位 "123456789012", // 12 位 "12812345678", // 第二位是 2 "abcdefghijk" // 非数字 }; // Act & Assert foreach (var mobile in invalidMobiles) Assert.IsFalse(ValidationHelper.IsValidChinaMobile(mobile), $"Should fail for: {mobile}"); } [TestMethod] public void ValidateChinaMobile_ValidMobile_ReturnsSuccess() { // Arrange var mobile = "13812345678"; // Act var result = ValidationHelper.ValidateChinaMobile(mobile); // Assert Assert.IsTrue(result.IsSuccess); Assert.AreEqual(mobile, result.Value); } [TestMethod] public void IsValidInternationalMobile_ValidFormats_ReturnsTrue() { // Arrange var validMobiles = new[] { "+86-13812345678", "+1-5551234567", "+44 7911123456", "+8613812345678" }; // Act & Assert foreach (var mobile in validMobiles) Assert.IsTrue(ValidationHelper.IsValidInternationalMobile(mobile), $"Failed for: {mobile}"); } #endregion #region 身份证验证测试 [TestMethod] public void IsValidChinaIdCard_ValidIdCards_ReturnsTrue() { // Arrange: 测试有效的身份证号(包含正确的校验码) var validIdCards = new[] { "11010519491231002X", // 北京,1949年12月31日,校验码 X "110105194912310021" // 北京,1949年12月31日,校验码 1 }; // Act & Assert foreach (var idCard in validIdCards) { var isValid = ValidationHelper.IsValidChinaIdCard(idCard); // 注意:这里不能保证所有测试身份证都是真实有效的,只是格式和校验码正确 } } [TestMethod] public void ValidateChinaIdCard_InvalidFormat_ReturnsFailure() { // Arrange var invalidIdCards = new[] { "", "12345", // 太短 "123456789012345678", // 格式不对(日期无效) "11010519491399002X" // 无效日期(99号) }; // Act & Assert foreach (var idCard in invalidIdCards) { var result = ValidationHelper.ValidateChinaIdCard(idCard); Assert.IsTrue(result.IsFailure, $"Should fail for: {idCard}"); } } [TestMethod] public void ExtractBirthDateFromIdCard_ValidIdCard_ReturnsCorrectDate() { // Arrange: 110105199001150011 表示 1990年1月15日 var idCard = "110105199001150011"; // Act var birthDate = ValidationHelper.ExtractBirthDateFromIdCard(idCard); // Assert Assert.IsNotNull(birthDate); Assert.AreEqual(1990, birthDate.Value.Year); Assert.AreEqual(1, birthDate.Value.Month); Assert.AreEqual(15, birthDate.Value.Day); } [TestMethod] public void ExtractGenderFromIdCard_ValidIdCard_ReturnsCorrectGender() { // Arrange var maleIdCard = "110105199001150011"; // 倒数第二位是 1(奇数) var femaleIdCard = "110105199001150024"; // 倒数第二位是 2(偶数) // Act var maleGender = ValidationHelper.ExtractGenderFromIdCard(maleIdCard); var femaleGender = ValidationHelper.ExtractGenderFromIdCard(femaleIdCard); // Assert Assert.AreEqual("Male", maleGender); Assert.AreEqual("Female", femaleGender); } #endregion #region URL 验证测试 [TestMethod] public void IsValidUrl_ValidUrls_ReturnsTrue() { // Arrange var validUrls = new[] { "http://example.com", "https://www.example.com", "https://example.com/path/to/page?query=value", "http://subdomain.example.com:8080" }; // Act & Assert foreach (var url in validUrls) Assert.IsTrue(ValidationHelper.IsValidUrl(url), $"Failed for: {url}"); } [TestMethod] public void IsValidUrl_InvalidUrls_ReturnsFalse() { // Arrange var invalidUrls = new[] { "", "not-a-url", "ftp://example.com", // 不是 HTTP/HTTPS "//example.com", "example.com" // 缺少协议 }; // Act & Assert foreach (var url in invalidUrls) Assert.IsFalse(ValidationHelper.IsValidUrl(url), $"Should fail for: {url}"); } [TestMethod] public void ValidateUrl_ValidUrl_ReturnsSuccess() { // Arrange var url = "https://www.example.com"; // Act var result = ValidationHelper.ValidateUrl(url); // Assert Assert.IsTrue(result.IsSuccess); Assert.AreEqual(url, result.Value); } #endregion #region 数值范围验证测试 [TestMethod] public void ValidateRange_ValueInRange_ReturnsSuccess() { // Arrange & Act var result = ValidationHelper.ValidateRange(50, 1, 100); // Assert Assert.IsTrue(result.IsSuccess); Assert.AreEqual(50, result.Value); } [TestMethod] public void ValidateRange_ValueOutOfRange_ReturnsFailure() { // Arrange & Act var tooSmall = ValidationHelper.ValidateRange(0, 1, 100, "年龄"); var tooLarge = ValidationHelper.ValidateRange(150, 1, 100, "年龄"); // Assert Assert.IsTrue(tooSmall.IsFailure); Assert.IsTrue(tooSmall.ErrorMessage.Contains("年龄")); Assert.IsTrue(tooLarge.IsFailure); } [TestMethod] public void ValidateRange_DoubleValue_Works() { // Arrange & Act var valid = ValidationHelper.ValidateRange(3.14, 0.0, 10.0, "比率"); var invalid = ValidationHelper.ValidateRange(15.0, 0.0, 10.0, "比率"); // Assert Assert.IsTrue(valid.IsSuccess); Assert.IsTrue(invalid.IsFailure); } #endregion #region 字符串长度验证测试 [TestMethod] public void ValidateLength_ValidLength_ReturnsSuccess() { // Arrange var value = "Hello"; // Act var result = ValidationHelper.ValidateLength(value, 3, 10, "用户名"); // Assert Assert.IsTrue(result.IsSuccess); Assert.AreEqual(value, result.Value); } [TestMethod] public void ValidateLength_TooShort_ReturnsFailure() { // Arrange var value = "ab"; // Act var result = ValidationHelper.ValidateLength(value, 3, 10, "用户名"); // Assert Assert.IsTrue(result.IsFailure); Assert.IsTrue(result.ErrorMessage.Contains("不能少于")); } [TestMethod] public void ValidateNotEmpty_EmptyString_ReturnsFailure() { // Arrange & Act var result1 = ValidationHelper.ValidateNotEmpty("", "用户名"); var result2 = ValidationHelper.ValidateNotEmpty(" ", "用户名"); var result3 = ValidationHelper.ValidateNotEmpty(null, "用户名"); // Assert Assert.IsTrue(result1.IsFailure); Assert.IsTrue(result2.IsFailure); Assert.IsTrue(result3.IsFailure); } #endregion #region 密码强度验证测试 [TestMethod] public void IsStrongPassword_StrongPassword_ReturnsTrue() { // Arrange var strongPasswords = new[] { "Abc123!@", "P@ssw0rd", "MySecure123!" }; // Act & Assert foreach (var password in strongPasswords) Assert.IsTrue(ValidationHelper.IsStrongPassword(password), $"Failed for: {password}"); } [TestMethod] public void IsStrongPassword_WeakPassword_ReturnsFalse() { // Arrange var weakPasswords = new[] { "12345678", // 只有数字 "abcdefgh", // 只有小写 "ABCDEFGH", // 只有大写 "Abc123", // 太短 "Abcdefgh" // 缺少数字和特殊字符 }; // Act & Assert foreach (var password in weakPasswords) Assert.IsFalse(ValidationHelper.IsStrongPassword(password), $"Should fail for: {password}"); } [TestMethod] public void ValidatePassword_WeakPassword_ReturnsFailureWithDetails() { // Arrange var password = "weakpass"; // Act var result = ValidationHelper.ValidatePassword(password); // Assert Assert.IsTrue(result.IsFailure); Assert.IsTrue(result.ErrorMessage.Contains("数字")); Assert.IsTrue(result.ErrorMessage.Contains("大写")); Assert.IsTrue(result.ErrorMessage.Contains("特殊字符")); } #endregion #region IP 地址验证测试 [TestMethod] public void IsValidIPv4_ValidIPs_ReturnsTrue() { // Arrange var validIPs = new[] { "192.168.1.1", "10.0.0.1", "172.16.0.1", "8.8.8.8" }; // Act & Assert foreach (var ip in validIPs) Assert.IsTrue(ValidationHelper.IsValidIPv4(ip), $"Failed for: {ip}"); } [TestMethod] public void IsValidIPv4_InvalidIPs_ReturnsFalse() { // Arrange var invalidIPs = new[] { "", "256.1.1.1", // 超出范围 "192.168.1", // 不完整 "192.168.1.1.1", // 太多段 "not.an.ip.address" }; // Act & Assert foreach (var ip in invalidIPs) Assert.IsFalse(ValidationHelper.IsValidIPv4(ip), $"Should fail for: {ip}"); } #endregion #region 组合验证测试 [TestMethod] public void ValidateAll_AllPass_ReturnsSuccess() { // Arrange var email = "test@example.com"; // Act: 组合多个验证规则 var result = ValidationHelper.ValidateAll( email, e => ValidationHelper.ValidateNotEmpty(e, "邮箱"), e => ValidationHelper.ValidateLength(e, 5, 50, "邮箱"), e => ValidationHelper.ValidateEmail(e) ); // Assert Assert.IsTrue(result.IsSuccess); } [TestMethod] public void ValidateAll_OneFails_ReturnsFailure() { // Arrange var email = "ab"; // 太短 // Act var result = ValidationHelper.ValidateAll( email, e => ValidationHelper.ValidateNotEmpty(e, "邮箱"), e => ValidationHelper.ValidateLength(e, 5, 50, "邮箱"), e => ValidationHelper.ValidateEmail(e) ); // Assert Assert.IsTrue(result.IsFailure); Assert.IsTrue(result.ErrorMessage.Contains("长度")); } [TestMethod] public void ValidateAny_OnePass_ReturnsSuccess() { // Arrange: 可以是邮箱或手机号 var input = "test@example.com"; // Act var result = ValidationHelper.ValidateAny( input, i => ValidationHelper.ValidateEmail(i), i => ValidationHelper.ValidateChinaMobile(i) ); // Assert Assert.IsTrue(result.IsSuccess); } [TestMethod] public void ValidateAny_NonPass_ReturnsFailure() { // Arrange var input = "invalid"; // Act var result = ValidationHelper.ValidateAny( input, i => ValidationHelper.ValidateEmail(i), i => ValidationHelper.ValidateChinaMobile(i) ); // Assert Assert.IsTrue(result.IsFailure); } #endregion #region 实际应用场景测试 [TestMethod] public void Scenario_UserRegistrationValidation() { // Arrange: 模拟用户注册数据 var email = "user@example.com"; var password = "SecurePass123!"; var mobile = "13812345678"; // Act: 验证所有字段 var emailResult = ValidationHelper.ValidateEmail(email); var passwordResult = ValidationHelper.ValidatePassword(password); var mobileResult = ValidationHelper.ValidateChinaMobile(mobile); // Assert Assert.IsTrue(emailResult.IsSuccess); Assert.IsTrue(passwordResult.IsSuccess); Assert.IsTrue(mobileResult.IsSuccess); } [TestMethod] public void Scenario_FormValidationWithMultipleFields() { // Arrange: 表单数据 var formData = new { Email = "invalid-email", Password = "weak", Age = 200 }; // Act: 验证各字段 var results = new { Email = ValidationHelper.ValidateEmail(formData.Email), Password = ValidationHelper.ValidatePassword(formData.Password), Age = ValidationHelper.ValidateRange(formData.Age, 0, 150, "年龄") }; // Assert: 收集所有错误 var errors = new List(); if (results.Email.IsFailure) errors.Add(results.Email.ErrorMessage); if (results.Password.IsFailure) errors.Add(results.Password.ErrorMessage); if (results.Age.IsFailure) errors.Add(results.Age.ErrorMessage); Assert.AreEqual(3, errors.Count); // 所有字段都有错误 Assert.IsTrue(errors[0].Contains("邮箱")); Assert.IsTrue(errors[1].Contains("密码")); Assert.IsTrue(errors[2].Contains("年龄")); } [TestMethod] public void Scenario_ChainedValidation() { // Arrange var userInput = "test@example.com"; // Act: 链式验证 var result = ValidationHelper.ValidateNotEmpty(userInput, "邮箱") .Bind(e => ValidationHelper.ValidateLength(e, 5, 100, "邮箱")) .Bind(e => ValidationHelper.ValidateEmail(e)); // Assert Assert.IsTrue(result.IsSuccess); } #endregion }