Files
planet/backend/tests/test_security.py
2026-03-05 11:46:58 +08:00

114 lines
4.0 KiB
Python

"""Unit tests for security module"""
import pytest
from datetime import datetime, timedelta
from jose import jwt
from unittest.mock import MagicMock
from app.core.security import (
create_access_token,
create_refresh_token,
verify_password,
get_password_hash,
)
from app.core.config import settings
class TestPasswordHashing:
"""Tests for password hashing functions"""
def test_hash_password(self):
"""Test password hashing"""
password = "test_password_123"
hashed = get_password_hash(password)
assert hashed != password
assert len(hashed) > 0
def test_verify_correct_password(self):
"""Test verification of correct password"""
password = "test_password_123"
hashed = get_password_hash(password)
assert verify_password(password, hashed) is True
def test_verify_incorrect_password(self):
"""Test verification of incorrect password"""
password = "test_password_123"
hashed = get_password_hash(password)
assert verify_password("wrong_password", hashed) is False
def test_hash_is_unique(self):
"""Test that hashes are unique for same password"""
password = "test_password_123"
hash1 = get_password_hash(password)
hash2 = get_password_hash(password)
assert hash1 != hash2 # bcrypt adds salt
class TestTokenCreation:
"""Tests for token creation functions"""
def test_create_access_token(self):
"""Test access token creation"""
data = {"sub": "123", "username": "testuser"}
token = create_access_token(data)
assert token is not None
assert len(token) > 0
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
assert payload["sub"] == "123"
assert payload["username"] == "testuser"
assert payload["type"] == "access"
def test_create_refresh_token(self):
"""Test refresh token creation"""
data = {"sub": "123"}
token = create_refresh_token(data)
assert token is not None
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
assert payload["sub"] == "123"
assert payload["type"] == "refresh"
def test_access_token_expiration(self):
"""Test access token has correct expiration"""
data = {"sub": "123"}
token = create_access_token(data)
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
exp_timestamp = payload["exp"]
# Token should expire in approximately 15 minutes (accounting for timezone)
expected_minutes = settings.ACCESS_TOKEN_EXPIRE_MINUTES
# The timestamp is in seconds since epoch
import time
now_timestamp = time.time()
minutes_diff = (exp_timestamp - now_timestamp) / 60
assert expected_minutes - 1 < minutes_diff < expected_minutes + 1
def test_refresh_token_expiration(self):
"""Test refresh token has correct expiration"""
data = {"sub": "123"}
token = create_refresh_token(data)
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
exp = datetime.fromtimestamp(payload["exp"])
now = datetime.utcnow()
# Token should expire in approximately 7 days (with some tolerance)
delta = exp - now
assert delta.days >= 6 # At least 6 days
assert delta.days <= 8 # Less than 8 days
class TestJWTSecurity:
"""Tests for JWT security features"""
def test_invalid_token_raises_error(self):
"""Test that invalid token raises JWTError"""
with pytest.raises(jwt.JWTError):
jwt.decode("invalid_token", settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
def test_token_with_wrong_secret_raises_error(self):
"""Test that token with wrong secret raises error"""
data = {"sub": "123"}
token = create_access_token(data)
with pytest.raises(jwt.JWTError):
jwt.decode(token, "wrong_secret", algorithms=[settings.ALGORITHM])