Add tests for auth dependencies and security utilities
Introduced unit tests for `get_current_user`, `get_current_active_user`, and security functions like token creation and decoding. Also refactored imports for consistency and cleaned up unused or misplaced code to improve maintainability.
This commit is contained in:
75
backend/tests/auth/dependencies.py
Normal file
75
backend/tests/auth/dependencies.py
Normal file
@@ -0,0 +1,75 @@
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
from jose import jwt
|
||||
|
||||
from app.auth.dependencies import get_current_user, get_current_active_user
|
||||
from app.auth.security import SECRET_KEY, ALGORITHM
|
||||
from app.models.user import User
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_user():
|
||||
return User(
|
||||
id="123e4567-e89b-12d3-a456-426614174000",
|
||||
email="test@example.com",
|
||||
password_hash="hashedpassword",
|
||||
is_active=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_current_user_success(mock_user):
|
||||
valid_token = jwt.encode({"sub": str(mock_user.id), "type": "access"}, SECRET_KEY, algorithm=ALGORITHM)
|
||||
|
||||
mock_db = AsyncMock()
|
||||
mock_db.get.return_value = mock_user
|
||||
|
||||
user = await get_current_user(token=valid_token, db=mock_db)
|
||||
assert user == mock_user
|
||||
mock_db.get.assert_called_once_with(User, mock_user.id)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_current_user_invalid_token():
|
||||
invalid_token = "invalid.token.payload"
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
await get_current_user(token=invalid_token, db=AsyncMock())
|
||||
|
||||
assert exc_info.value.status_code == 401
|
||||
assert exc_info.value.detail == "Could not validate credentials"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_current_user_wrong_token_type():
|
||||
token = jwt.encode({"sub": "123", "type": "refresh"}, SECRET_KEY, algorithm=ALGORITHM)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
await get_current_user(token=token, db=AsyncMock())
|
||||
|
||||
assert exc_info.value.status_code == 401
|
||||
assert exc_info.value.detail == "Could not validate credentials"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_current_active_user_success(mock_user):
|
||||
result = await get_current_active_user(mock_user)
|
||||
assert result == mock_user
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_current_active_user_inactive():
|
||||
inactive_user = User(
|
||||
id="123e4567-e89b-12d3-a456-426614174000",
|
||||
email="inactive@example.com",
|
||||
password_hash="hashedpassword",
|
||||
is_active=False
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
await get_current_active_user(inactive_user)
|
||||
|
||||
assert exc_info.value.status_code == 400
|
||||
assert exc_info.value.detail == "Inactive user"
|
||||
68
backend/tests/auth/test_security.py
Normal file
68
backend/tests/auth/test_security.py
Normal file
@@ -0,0 +1,68 @@
|
||||
import pytest
|
||||
from datetime import timedelta
|
||||
from jose import jwt, JWTError
|
||||
from app.auth.security import (
|
||||
get_password_hash, verify_password,
|
||||
create_access_token, create_refresh_token,
|
||||
decode_token, SECRET_KEY, ALGORITHM
|
||||
)
|
||||
from app.schemas.token import TokenPayload
|
||||
|
||||
|
||||
def test_password_hashing():
|
||||
plain_password = "securepassword123"
|
||||
hashed_password = get_password_hash(plain_password)
|
||||
|
||||
# Ensure hashed passwords are not the same
|
||||
assert hashed_password != plain_password
|
||||
# Test password verification
|
||||
assert verify_password(plain_password, hashed_password)
|
||||
assert not verify_password("wrongpassword", hashed_password)
|
||||
|
||||
|
||||
def test_access_token_creation():
|
||||
user_id = "123e4567-e89b-12d3-a456-426614174000"
|
||||
token = create_access_token({"sub": user_id})
|
||||
decoded_payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
||||
|
||||
assert decoded_payload.get("sub") == user_id
|
||||
assert decoded_payload.get("type") == "access"
|
||||
|
||||
|
||||
def test_refresh_token_creation():
|
||||
user_id = "123e4567-e89b-12d3-a456-426614174000"
|
||||
token = create_refresh_token({"sub": user_id})
|
||||
decoded_payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
||||
|
||||
assert decoded_payload.get("sub") == user_id
|
||||
assert decoded_payload.get("type") == "refresh"
|
||||
|
||||
|
||||
def test_decode_token_valid():
|
||||
user_id = "123e4567-e89b-12d3-a456-426614174000"
|
||||
access_token = create_access_token({"sub": user_id})
|
||||
token_payload = decode_token(access_token)
|
||||
|
||||
assert isinstance(token_payload, TokenPayload)
|
||||
assert token_payload.sub == user_id
|
||||
assert token_payload.type == "access"
|
||||
|
||||
|
||||
def test_decode_token_expired():
|
||||
user_id = "123e4567-e89b-12d3-a456-426614174000"
|
||||
token = create_access_token({"sub": user_id}, expires_delta=timedelta(seconds=-1))
|
||||
|
||||
with pytest.raises(JWTError):
|
||||
decode_token(token)
|
||||
|
||||
|
||||
def test_decode_token_invalid_signature():
|
||||
token = jwt.encode({"some": "data"}, "invalid_key", algorithm=ALGORITHM)
|
||||
with pytest.raises(JWTError):
|
||||
decode_token(token)
|
||||
|
||||
|
||||
def test_decode_token_malformed():
|
||||
malformed_token = "malformed.header.payload"
|
||||
with pytest.raises(JWTError):
|
||||
decode_token(malformed_token)
|
||||
Reference in New Issue
Block a user