Files
ENI-PythonAdvanced_10/tests/etape2_dal_repositories.py
2025-12-17 13:29:14 +01:00

140 lines
4.9 KiB
Python

"""
Tests de validation pour l'Étape 2 : Couche d'accès aux données (Repositories)
[Version Corrigée]
Cette version corrige les assertions pour accepter les arguments positionnels (args)
au lieu de forcer les arguments mots-clés (kwargs) lors de l'appel à _request.
Elle corrige également la simulation de DALException pour qu'elle corresponde
à la logique de _base_client.py.
"""
import pytest
import pytest_asyncio
from unittest.mock import MagicMock, AsyncMock
from app.core.exceptions import DALException
from app.models.movie import Movie
from app.models.genre import Genre
# --- Fixtures de données (simule les réponses de l'API) ---
@pytest.fixture
def mock_movie_data():
"""Données JSON brutes pour un film, simulées depuis l'API."""
return {
"id": 1,
"title": "Inception",
"year": 2010,
"duration": 148,
"synopsis": "Un voleur...",
"genre": {"id": 1, "label": "Science-Fiction"},
"director": {"id": 1, "last_name": "Nolan", "first_name": "Christopher"},
"actors": [{"id": 2, "last_name": "DiCaprio", "first_name": "Leonardo"}],
"opinions": []
}
@pytest.fixture
def mock_genre_list_data():
"""Données JSON brutes pour une liste de genres."""
return [
{"id": 1, "label": "Science-Fiction"},
{"id": 2, "label": "Drame"}
]
# --- Tests ---
@pytest.mark.asyncio
async def test_movie_repo_find_by_id_success(mocker, mock_movie_data):
"""
Vérifie que movie_repository.find_by_id retourne un objet Movie
en cas de succès.
"""
# 1. Mock de l'api_client
mock_response = MagicMock()
mock_response.json.return_value = mock_movie_data
mock_api_client = AsyncMock()
mock_api_client._request.return_value = mock_response
# On "patch" l'instance importée dans le module du repository
mocker.patch('app.repositories.movie_repository.api_client', mock_api_client)
# 2. Appel de la méthode à tester
from app.repositories.movie_repository import movie_repository
movie = await movie_repository.find_by_id(1)
# 3. Assertions
mock_api_client._request.assert_called_once_with("GET", "/movies/1")
assert movie is not None
assert isinstance(movie, Movie)
assert movie.title == "Inception"
@pytest.mark.asyncio
async def test_movie_repo_find_by_id_not_found(mocker):
"""
Vérifie que movie_repository.find_by_id retourne None si l'API
lève une DALException avec un status 404.
"""
# 1. Mock de l'api_client pour qu'il lève une erreur 404
mock_api_client = AsyncMock()
# 1. Crée l'exception
mock_exception = DALException("Not Found")
# 2. Attache le status_code
mock_exception.status_code = 404
# 3. La définit comme side_effect
mock_api_client._request.side_effect = mock_exception
mocker.patch('app.repositories.movie_repository.api_client', mock_api_client)
# 2. Appel de la méthode à tester
from app.repositories.movie_repository import movie_repository
movie = await movie_repository.find_by_id(999)
# 3. Assertions
mock_api_client._request.assert_called_once_with("GET", "/movies/999")
assert movie is None
@pytest.mark.asyncio
async def test_movie_repo_list(mocker, mock_movie_data):
"""
Vérifie que movie_repository.list retourne une liste de Movies
et passe correctement les paramètres skip/limit.
"""
# 1. Mock de l'api_client
mock_response = MagicMock()
mock_response.json.return_value = [mock_movie_data] # L'API retourne une liste
mock_api_client = AsyncMock()
mock_api_client._request.return_value = mock_response
mocker.patch('app.repositories.movie_repository.api_client', mock_api_client)
# 2. Appel de la méthode à tester
from app.repositories.movie_repository import movie_repository
movies = await movie_repository.list(skip=5, limit=10)
# 3. Assertions
expected_params = {"skip": 5, "limit": 10}
mock_api_client._request.assert_called_once_with("GET", "/movies/", params=expected_params)
assert isinstance(movies, list)
assert isinstance(movies[0], Movie)
assert movies[0].id == 1
@pytest.mark.asyncio
async def test_genre_repo_list(mocker, mock_genre_list_data):
"""
Vérifie que genre_repository.list retourne une liste de Genres.
"""
# 1. Mock de l'api_client
mock_response = MagicMock()
mock_response.json.return_value = mock_genre_list_data
mock_api_client = AsyncMock()
mock_api_client._request.return_value = mock_response
mocker.patch('app.repositories.genre_repository.api_client', mock_api_client)
# 2. Appel de la méthode à tester
from app.repositories.genre_repository import genre_repository
genres = await genre_repository.list()
# 3. Assertions
mock_api_client._request.assert_called_once_with("GET", "/genres/")
assert isinstance(genres, list)
assert isinstance(genres[0], Genre)
assert genres[0].label == "Science-Fiction"