Add unit tests for models and services

- Implemented unit tests for Object model including folder and file creation, properties, and path retrieval.
- Added unit tests for Setting model covering creation, unique constraints, and type enumeration.
- Created unit tests for User model focusing on user creation, uniqueness, and group relationships.
- Developed unit tests for Login service to validate login functionality, including 2FA and token generation.
- Added utility tests for JWT creation and verification, ensuring token integrity and expiration handling.
- Implemented password utility tests for password generation, hashing, and TOTP verification.
This commit is contained in:
2025-12-19 19:48:05 +08:00
parent 51b6de921b
commit f93cb3eedb
60 changed files with 8189 additions and 117 deletions

View File

@@ -0,0 +1,138 @@
"""
Password 工具类的单元测试
"""
import pytest
from utils.password.pwd import Password, PasswordStatus
def test_password_generate_default_length():
"""测试默认长度生成密码"""
password = Password.generate()
# 默认长度为 8token_hex 生成的是16进制字符串长度是原始长度的2倍
assert len(password) == 16
assert isinstance(password, str)
def test_password_generate_custom_length():
"""测试自定义长度生成密码"""
length = 12
password = Password.generate(length=length)
assert len(password) == length * 2
assert isinstance(password, str)
def test_password_hash():
"""测试密码哈希"""
plain_password = "my_secure_password_123"
hashed = Password.hash(plain_password)
assert hashed != plain_password
assert isinstance(hashed, str)
# Argon2 哈希以 $argon2 开头
assert hashed.startswith("$argon2")
def test_password_verify_valid():
"""测试正确密码验证"""
plain_password = "correct_password"
hashed = Password.hash(plain_password)
status = Password.verify(hashed, plain_password)
assert status == PasswordStatus.VALID
def test_password_verify_invalid():
"""测试错误密码验证"""
plain_password = "correct_password"
wrong_password = "wrong_password"
hashed = Password.hash(plain_password)
status = Password.verify(hashed, wrong_password)
assert status == PasswordStatus.INVALID
def test_password_verify_expired():
"""测试密码哈希过期检测"""
# 注意: 实际检测需要修改 Argon2 参数,这里只是测试接口
# 在真实场景中,当哈希参数过时时会返回 EXPIRED
plain_password = "password"
hashed = Password.hash(plain_password)
status = Password.verify(hashed, plain_password)
# 新生成的哈希应该是 VALID
assert status in [PasswordStatus.VALID, PasswordStatus.EXPIRED]
@pytest.mark.asyncio
async def test_totp_generate():
"""测试 TOTP 密钥生成"""
username = "testuser"
response = await Password.generate_totp(username)
assert response.setup_token is not None
assert response.uri is not None
assert isinstance(response.setup_token, str)
assert isinstance(response.uri, str)
# TOTP URI 格式: otpauth://totp/...
assert response.uri.startswith("otpauth://totp/")
assert username in response.uri
def test_totp_verify_valid():
"""测试 TOTP 验证正确"""
import pyotp
# 生成密钥
secret = pyotp.random_base32()
# 生成当前有效的验证码
totp = pyotp.TOTP(secret)
valid_code = totp.now()
# 验证
status = Password.verify_totp(secret, valid_code)
assert status == PasswordStatus.VALID
def test_totp_verify_invalid():
"""测试 TOTP 验证错误"""
import pyotp
secret = pyotp.random_base32()
invalid_code = "000000" # 几乎不可能是当前有效码
status = Password.verify_totp(secret, invalid_code)
# 注意: 极小概率 000000 恰好是有效码,但实际测试中基本不会发生
assert status == PasswordStatus.INVALID
def test_password_hash_consistency():
"""测试相同密码多次哈希结果不同(盐随机)"""
password = "test_password"
hash1 = Password.hash(password)
hash2 = Password.hash(password)
# 由于盐是随机的,两次哈希结果应该不同
assert hash1 != hash2
# 但都应该能通过验证
assert Password.verify(hash1, password) == PasswordStatus.VALID
assert Password.verify(hash2, password) == PasswordStatus.VALID
def test_password_generate_uniqueness():
"""测试生成的密码唯一性"""
passwords = [Password.generate() for _ in range(100)]
# 100个密码应该都不相同
assert len(set(passwords)) == 100