A:Common配置
This commit is contained in:
1 parent
61e769a0f6
commit
c8fde9759f
8 files changed
+3742
-703
No files matched your search
@@ -0,0 +1,624 @@
|
||||
using Common.Utils;
|
||||
|
||||
namespace Common.Test;
|
||||
|
||||
/// <summary>
|
||||
/// ValidationHelper 验证工具测试
|
||||
/// 展示各种数据验证功能和 Result 模式集成
|
||||
/// </summary>
|
||||
[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<string>();
|
||||
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
|
||||
}
|
||||
Reference in new issue
Block a user