First commit
This commit is contained in:
140
tests/etape2_dal_repositories.py
Normal file
140
tests/etape2_dal_repositories.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""
|
||||
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"
|
||||
Reference in New Issue
Block a user