Added unit tests for user api

This commit is contained in:
2025-09-26 21:48:20 +02:00
parent 42db3daa31
commit b0289d865c
2 changed files with 168 additions and 1 deletions

View File

@@ -79,7 +79,7 @@ def get_current_user(
return user
def get_admin_user(current_user: UserInDB = Depends(get_current_user)) -> UserInDB:
def get_admin_user(current_user: UserInDB = Depends(get_current_user)) -> UserInDB:
"""
Dependency to ensure current user has admin role.

167
tests/api/test_users.py Normal file
View File

@@ -0,0 +1,167 @@
# File: tests/api/test_users.py
from datetime import datetime
from unittest.mock import MagicMock
import pytest
from fastapi import status
from fastapi.testclient import TestClient
from app.api.dependencies import get_admin_user, get_user_service
from app.main import app
from app.models.auth import UserRole
from app.models.types import PyObjectId
from app.models.user import UserInDB, UserCreate
from app.services.user_service import UserService
# -----------------------
# Fixtures
# -----------------------
@pytest.fixture
def fake_user_admin():
return UserInDB(
_id=PyObjectId(),
username="admin",
email="admin@example.com",
role=UserRole.ADMIN,
is_active=True,
hashed_password="hashed-secret",
created_at=datetime(2025, 1, 1),
updated_at=datetime(2025, 1, 2),
)
@pytest.fixture
def fake_user_response():
return UserInDB(
_id=PyObjectId(),
username="other",
email="other@example.com",
role=UserRole.USER,
is_active=True,
hashed_password="hashed-secret-2",
created_at=datetime(2025, 1, 1),
updated_at=datetime(2025, 1, 2),
)
@pytest.fixture
def client(fake_user_admin):
# Fake admin dependency
def get_admin_user_override():
return fake_user_admin
# Fake user service
user_service_mock = MagicMock(spec=UserService)
def get_user_service_override():
return user_service_mock
client = TestClient(app)
client.app.dependency_overrides = {
get_admin_user: get_admin_user_override,
get_user_service: get_user_service_override
}
client.user_service_mock = user_service_mock
return client
# -----------------------
# Tests
# -----------------------
class TestListUsers:
def test_i_can_list_users(self, client, fake_user_admin, fake_user_response):
client.user_service_mock.list_users.return_value = [fake_user_admin, fake_user_response]
response = client.get("/users")
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) == 2
assert data[0]["username"] == "admin"
def test_i_can_list_users_when_empty(self, client):
client.user_service_mock.list_users.return_value = []
response = client.get("/users")
assert response.status_code == status.HTTP_200_OK
assert response.json() == []
class TestGetUserById:
def test_i_can_get_user_by_id(self, client, fake_user_response):
client.user_service_mock.get_user_by_id.return_value = fake_user_response
response = client.get(f"/users/{fake_user_response.id}")
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert data["username"] == fake_user_response.username
def test_i_cannot_get_user_by_id_not_found(self, client):
client.user_service_mock.get_user_by_id.return_value = None
response = client.get("/users/64f0c9f4b0d1c8b7b8e1f0a2")
assert response.status_code == status.HTTP_404_NOT_FOUND
assert response.json()["detail"] == "User not found"
class TestCreateUser:
def test_i_can_create_user(self, client, fake_user_response):
user_data = UserCreate(username="newuser",
email="new@example.com",
password="#Passw0rd!",
role=UserRole.USER)
client.user_service_mock.create_user.return_value = fake_user_response
response = client.post("/users", json=user_data.model_dump(mode="json"))
assert response.status_code == status.HTTP_201_CREATED
data = response.json()
assert data["username"] == fake_user_response.username
def test_i_cannot_create_user_when_service_raises_value_error(self, client):
user_data = {"username": "baduser", "email": "bad@example.com", "role": "user", "password": "password"}
client.user_service_mock.create_user.side_effect = ValueError("Invalid data")
response = client.post("/users", json=user_data)
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
class TestUpdateUser:
def test_i_can_update_user(self, client, fake_user_response):
user_data = {"username": "updateduser", "email": "updated@example.com"}
client.user_service_mock.update_user.return_value = fake_user_response
response = client.put(f"/users/{fake_user_response.id}", json=user_data)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert data["username"] == fake_user_response.username
def test_i_cannot_update_user_not_found(self, client):
client.user_service_mock.update_user.return_value = None
user_data = {"username": "updateduser"}
response = client.put("/users/64f0c9f4b0d1c8b7b8e1f0a2", json=user_data)
assert response.status_code == status.HTTP_404_NOT_FOUND
assert response.json()["detail"] == "User not found"
def test_i_cannot_update_user_when_service_raises_value_error(self, client):
client.user_service_mock.update_user.side_effect = ValueError("Invalid update")
user_data = {"username": "badupdate"}
response = client.put("/users/64f0c9f4b0d1c8b7b8e1f0a2", json=user_data)
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert response.json()["detail"] == "Invalid update"
class TestDeleteUser:
def test_i_can_delete_user(self, client):
client.user_service_mock.delete_user.return_value = True
response = client.delete("/users/64f0c9f4b0d1c8b7b8e1f0a1")
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert data["message"] == "User successfully deleted"
def test_i_cannot_delete_user_not_found(self, client):
client.user_service_mock.delete_user.return_value = False
response = client.delete("/users/64f0c9f4b0d1c8b7b8e1f0a2")
assert response.status_code == status.HTTP_404_NOT_FOUND
assert response.json()["detail"] == "User not found"