Files
xiaoxia-saas/tests/unit/test_password_hasher.py
T
CI Test 9d54b3e586
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
Deploy / Deploy Staging (push) Has been cancelled
Deploy / Build Production Runtime Images (push) Has been cancelled
Deploy / Deploy Production (push) Has been cancelled
Deploy / Production Browser E2E (push) Has been cancelled
fix: correct all import paths for jwt_service and password_hasher (move from domain to application)
2026-06-27 21:41:56 +08:00

173 lines
5.5 KiB
Python

"""
密码哈希工具测试
"""
import pytest
from packages.application.auth.password_hasher import PasswordHasher, PasswordValidator
class TestPasswordHasher:
"""密码哈希测试"""
@pytest.fixture
def hasher(self):
"""创建密码哈希器"""
return PasswordHasher(rounds=4) # 测试用低 cost,加快速度
def test_hash_password(self, hasher):
"""测试密码哈希"""
password = "MySecurePassword123"
hashed = hasher.hash_password(password)
assert isinstance(hashed, str)
assert len(hashed) > 0
assert hashed != password # 哈希后不等于原文
assert hashed.startswith("$2b$") # bcrypt 格式
def test_hash_same_password_different_result(self, hasher):
"""测试相同密码每次哈希结果不同(因为 salt 不同)"""
password = "MySecurePassword123"
hash1 = hasher.hash_password(password)
hash2 = hasher.hash_password(password)
assert hash1 != hash2 # salt 不同,哈希不同
def test_verify_correct_password(self, hasher):
"""测试验证正确的密码"""
password = "MySecurePassword123"
hashed = hasher.hash_password(password)
assert hasher.verify_password(password, hashed) is True
def test_verify_incorrect_password(self, hasher):
"""测试验证错误的密码"""
password = "MySecurePassword123"
hashed = hasher.hash_password(password)
assert hasher.verify_password("WrongPassword", hashed) is False
def test_verify_empty_password(self, hasher):
"""测试空密码验证"""
hashed = hasher.hash_password("test")
assert hasher.verify_password("", hashed) is False
def test_verify_empty_hash(self, hasher):
"""测试空哈希验证"""
assert hasher.verify_password("test", "") is False
def test_verify_invalid_hash(self, hasher):
"""测试无效的哈希"""
assert hasher.verify_password("test", "invalid-hash") is False
def test_hash_empty_password(self, hasher):
"""测试哈希空密码应该失败"""
with pytest.raises(ValueError, match="Password cannot be empty"):
hasher.hash_password("")
def test_invalid_rounds(self):
"""测试无效的 rounds 参数"""
with pytest.raises(ValueError, match="rounds must be between 4 and 31"):
PasswordHasher(rounds=2)
with pytest.raises(ValueError, match="rounds must be between 4 and 31"):
PasswordHasher(rounds=50)
def test_unicode_password(self, hasher):
"""测试 Unicode 密码"""
password = "密码123!@#"
hashed = hasher.hash_password(password)
assert hasher.verify_password(password, hashed) is True
assert hasher.verify_password("错误密码", hashed) is False
class TestPasswordValidator:
"""密码验证器测试"""
@pytest.fixture
def validator(self):
"""创建密码验证器"""
return PasswordValidator(
min_length=8,
require_uppercase=True,
require_lowercase=True,
require_digit=True,
require_special=False,
)
def test_valid_password(self, validator):
"""测试有效密码"""
valid, error = validator.validate("MyPassword123")
assert valid is True
assert error is None
def test_password_too_short(self, validator):
"""测试密码太短"""
valid, error = validator.validate("Pass1")
assert valid is False
assert "at least 8 characters" in error
def test_password_no_uppercase(self, validator):
"""测试没有大写字母"""
valid, error = validator.validate("mypassword123")
assert valid is False
assert "uppercase letter" in error
def test_password_no_lowercase(self, validator):
"""测试没有小写字母"""
valid, error = validator.validate("MYPASSWORD123")
assert valid is False
assert "lowercase letter" in error
def test_password_no_digit(self, validator):
"""测试没有数字"""
valid, error = validator.validate("MyPassword")
assert valid is False
assert "digit" in error
def test_password_with_special_chars(self):
"""测试要求特殊字符"""
validator = PasswordValidator(
min_length=8,
require_uppercase=True,
require_lowercase=True,
require_digit=True,
require_special=True,
)
# 没有特殊字符
valid, error = validator.validate("MyPassword123")
assert valid is False
assert "special character" in error
# 有特殊字符
valid, error = validator.validate("MyPassword123!")
assert valid is True
assert error is None
def test_empty_password(self, validator):
"""测试空密码"""
valid, error = validator.validate("")
assert valid is False
assert "cannot be empty" in error
def test_custom_min_length(self):
"""测试自定义最小长度"""
validator = PasswordValidator(
min_length=12,
require_uppercase=False,
require_lowercase=False,
require_digit=False,
require_special=False,
)
valid, error = validator.validate("short")
assert valid is False
assert "at least 12 characters" in error
valid, error = validator.validate("longenoughpassword")
assert valid is True
assert error is None