Simuler les appels aux LLM dans les tests
unittest.mock, fixtures pytest et enregistrement/relecture des réponses des LLM.
Simuler les appels aux LLM dans les tests est une leçon AI Agents gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Agents, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Agents comprend 4 leçons au total.
Qu'est-ce que la simulation ?
La simulation remplace une fonction ou un objet réel par une version factice qui renvoie des réponses contrôlées. Lors des tests d'agents, nous simulons les appels aux API LLM afin que les tests s'exécutent instantanément, ne coûtent rien et produisent des résultats prévisibles.
Le module Python unittest.mock est l'outil standard pour cela.
Notions de base de unittest.mock.patch()
unittest.mock.patch(target) remplace temporairement l'objet nommé pendant toute la durée d'un test. La target est une chaîne de caractères avec points qui pointe vers l'objet tel qu'il est importé dans le module testé.
from unittest.mock import patch, MagicMock
# The function under test calls openai.chat.completions.create
# We patch it so no real API call is made
def ask_llm(question: str) -> str:
import openai
client = openai.OpenAI(api_key='test')
resp = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': question}]
)
return resp.choices[0].message.content
with patch('openai.OpenAI') as mock_client_class:
mock_instance = MagicMock()
mock_client_class.return_value = mock_instance
mock_instance.chat.completions.create.return_value = MagicMock(
choices=[MagicMock(message=MagicMock(content='Paris'))]
)
result = ask_llm('Capital of France?')
print(result) # 'Paris' — no API call madeUtiliser patch comme décorateur dans pytest
Utilisé comme décorateur avec pytest, @patch() injecte la simulation comme paramètre de fonction. La simulation est automatiquement supprimée une fois le test terminé.
from unittest.mock import patch, MagicMock
import pytest
# Assume agent.py contains: import openai; client = openai.OpenAI(...)
@patch('agent.openai.OpenAI')
def test_agent_calls_llm(mock_openai_class):
# Set up the mock chain
mock_client = MagicMock()
mock_openai_class.return_value = mock_client
mock_client.chat.completions.create.return_value = MagicMock(
choices=[MagicMock(message=MagicMock(content='Paris is the capital of France.'))]
)
from agent import ask_llm
result = ask_llm('What is the capital of France?')
assert 'Paris' in result
mock_client.chat.completions.create.assert_called_once()Créer une réponse simulée réutilisable
Construire manuellement des objets de réponse simulés est verbeux. Créez une fonction utilitaire qui construit des objets simulés correctement structurés et correspondant à la forme des réponses du SDK OpenAI.
from unittest.mock import MagicMock
def make_mock_response(content: str, tool_calls: list = None) -> MagicMock:
message = MagicMock()
message.content = content
message.tool_calls = tool_calls or []
choice = MagicMock()
choice.message = message
choice.finish_reason = 'stop' if not tool_calls else 'tool_calls'
response = MagicMock()
response.choices = [choice]
response.usage = MagicMock(total_tokens=42)
return response
# Usage in tests:
# mock_create.return_value = make_mock_response('Hello!')
# mock_create.return_value = make_mock_response('', tool_calls=[...])
# --- demo ---
response = make_mock_response('The weather in Paris is 18C and sunny.')
print('content:', response.choices[0].message.content)
print('finish_reason:', response.choices[0].finish_reason)
print('total_tokens:', response.usage.total_tokens)
Simuler les appels d'outils dans les réponses
Lors du test de la logique d'appel d'outils d'un agent, la réponse simulée doit inclure un champ tool_calls correctement structuré afin que le code d'analyse de l'agent puisse le traiter correctement.
import json
from unittest.mock import MagicMock
def make_tool_call_response(tool_name: str, arguments: dict) -> MagicMock:
tool_call = MagicMock()
tool_call.id = 'call_abc123'
tool_call.type = 'function'
tool_call.function = MagicMock()
tool_call.function.name = tool_name
tool_call.function.arguments = json.dumps(arguments)
message = MagicMock()
message.content = None
message.tool_calls = [tool_call]
response = MagicMock()
response.choices = [MagicMock(message=message, finish_reason='tool_calls')]
return response
# mock.return_value = make_tool_call_response('search_web', {'query': 'Python tutorials'})
# --- demo ---
response = make_tool_call_response('search_web', {'query': 'Python tutorials'})
call = response.choices[0].message.tool_calls[0]
print('tool name:', call.function.name)
print('tool arguments:', call.function.arguments)
print('finish_reason:', response.choices[0].finish_reason)
Fonctions de préparation pytest pour la simulation
Les fonctions de préparation de pytest permettent de définir du code de préparation réutilisable. Créez une fonction de préparation qui applique un patch au client LLM et le fournit à tout test qui le demande — sans répétition.
import pytest
from unittest.mock import patch, MagicMock
@pytest.fixture
def mock_openai(make_mock_response):
with patch('myagent.client.chat.completions.create') as mock_create:
mock_create.return_value = MagicMock(
choices=[MagicMock(message=MagicMock(
content='Default mocked response',
tool_calls=[]
))]
)
yield mock_create
# Now any test can use it:
def test_agent_responds(mock_openai):
from myagent import agent
result = agent.run('Hello')
assert result is not None
mock_openai.assert_called_once()La fonction de préparation mocker de pytest-mock
pytest-mock fournit une fonction de préparation mocker qui simplifie l'application de patchs. Elle nettoie automatiquement les simulations et offre une syntaxe plus claire que unittest.mock.patch utilisé directement.
# pip install pytest-mock
# In your test file:
def test_agent_with_mocker(mocker):
mock_create = mocker.patch('myagent.client.chat.completions.create')
mock_create.return_value = mocker.MagicMock(
choices=[mocker.MagicMock(message=mocker.MagicMock(
content='Mocked answer',
tool_calls=[]
))]
)
from myagent import agent
result = agent.run('What is 2+2?')
assert 'answer' in result.lower() or '4' in result
mock_create.assert_called_once()
# No cleanup needed — mocker handles itEnregistrer et rejouer avec vcr.py
vcrpy enregistre les interactions HTTP réelles dans un fichier « cassette » lors de la première exécution, puis les rejoue lors des exécutions suivantes. C'est idéal pour tester du code qui utilise l'API HTTP brute plutôt qu'un SDK.
# pip install vcrpy
import vcr
import httpx
@vcr.use_cassette('fixtures/cassettes/openai_chat.yaml')
def test_with_recorded_response():
# First run: makes a real HTTP call and records it
# Subsequent runs: uses the recorded cassette (no network, no cost)
response = httpx.post(
'https://api.openai.com/v1/chat/completions',
json={'model': 'gpt-4o-mini', 'messages': [{'role': 'user', 'content': 'Hello'}]},
headers={'Authorization': 'Bearer YOUR_KEY'}
)
data = response.json()
assert data['choices'][0]['message']['content'] is not NoneVérifier qu'une simulation a été appelée correctement
Après un test, vérifiez que la simulation a été appelée avec les bons arguments. Cela détecte les erreurs où l'agent envoie le mauvais modèle, omet des paramètres ou transmet des messages incorrects.
from unittest.mock import patch, MagicMock, call
@patch('myagent.client.chat.completions.create')
def test_agent_sends_correct_model(mock_create):
mock_create.return_value = MagicMock(
choices=[MagicMock(message=MagicMock(content='ok', tool_calls=[]))]
)
from myagent import agent
agent.run('Hello')
# Verify the mock was called with correct arguments
mock_create.assert_called_once()
call_kwargs = mock_create.call_args.kwargs
assert call_kwargs['model'] == 'gpt-4o-mini'
assert len(call_kwargs['messages']) >= 1
assert call_kwargs['messages'][0]['role'] == 'system'Simuler des erreurs d'API dans les tests
Testez la manière dont votre agent gère les échecs des LLM en configurant la simulation pour qu'elle lève des exceptions. Cela vérifie votre gestion des erreurs et votre logique de nouvelle tentative sans provoquer de véritables défaillances d'API.
from unittest.mock import patch
import openai
@patch('myagent.client.chat.completions.create')
def test_agent_handles_rate_limit(mock_create):
# Simulate a rate limit error
mock_create.side_effect = openai.RateLimitError(
message='Rate limit exceeded',
response=None,
body=None
)
from myagent import agent
result = agent.run('Hello')
# Agent should handle this gracefully
assert result['error'] == 'rate_limit'
# or
assert result['retry_after'] is not NoneOrganiser les fonctions de préparation de simulation dans conftest.py
Placez les fonctions de préparation partagées dans conftest.py à la racine de votre répertoire de tests. pytest découvre automatiquement ce fichier et rend ces fonctions disponibles dans tous les fichiers de test, sans qu'il soit nécessaire de les importer.
# tests/conftest.py
import pytest
from unittest.mock import patch, MagicMock
@pytest.fixture(autouse=False)
def mock_llm():
with patch('myagent.client.chat.completions.create') as mock_create:
mock_create.return_value = MagicMock(
choices=[MagicMock(message=MagicMock(
content='Test response',
tool_calls=[]
))]
)
yield mock_create
@pytest.fixture
def mock_search_tool():
with patch('myagent.tools.search_web') as mock_search:
mock_search.return_value = [{'title': 'Test', 'url': 'https://example.com'}]
yield mock_searchVérification des connaissances : simuler les appels LLM
Testez votre compréhension des techniques de simulation pour les tests d'agents.
Récapitulatif : simuler les appels LLM dans les tests
Vous disposez maintenant des outils nécessaires pour écrire des tests unitaires d'agents rapides et fiables :
- Utilisez
unittest.mock.patch()pour remplacer les clients LLM par des simulations - Créez des fonctions utilitaires réutilisables pour les réponses simulées, correspondant à la forme des réponses du SDK
- Simulez les appels d'outils avec des champs
tool_callscorrectement structurés - Utilisez les fonctions de préparation pytest et
conftest.pypour partager les simulations entre les tests - Utilisez
pytest-mockpour bénéficier d'une syntaxe plus claire - Utilisez
vcrpypour enregistrer et rejouer les interactions HTTP réelles
Les simulations constituent la base d'une suite de tests d'agents rapide et facile à maintenir.
Questions Fréquemment Posées
La leçon « Simuler les appels aux LLM dans les tests » est-elle gratuite ?
Oui — le texte complet de « Simuler les appels aux LLM dans les tests » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Agents, passe à CoddyKit PRO. Le cours AI Agents comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Simuler les appels aux LLM dans les tests » ?
unittest.mock, fixtures pytest et enregistrement/relecture des réponses des LLM. Tu pratiques AI Agents avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer AI Agents ?
Aucune expérience préalable n'est requise. AI Agents sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Simuler les appels aux LLM dans les tests » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon AI Agents ?
Oui. Chaque leçon AI Agents inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Pourquoi tester les agents est différent
- Simuler les appels aux LLM dans les tests
- Tester les agents par assertions
- Tests d’intégration pour les pipelines d’agents