테스트에서 LLM 호출 모의 처리
unittest.mock, pytest 픽스처, LLM 응답 기록 및 재생을 다룹니다.
테스트에서 LLM 호출 모의 처리은(는) CoddyKit의 무료 AI Agents 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Agents 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
모의 객체란 무엇인가요?
모의 처리란 실제 함수나 객체를 제어된 응답을 반환하는 가짜 버전으로 일시적으로 바꾸는 것입니다. 에이전트 검사에서는 LLM API 호출을 모의 처리하므로 검사를 즉시 실행하고 비용을 들이지 않으며 예측 가능한 결과를 얻을 수 있습니다.
Python의 unittest.mock 모듈은 이를 위한 표준 도구입니다.
unittest.mock.patch() 기초
unittest.mock.patch(target)는 검사 기간 동안 지정된 객체를 일시적으로 바꿉니다. target은 검사 대상 모듈에서 객체를 가져오는 방식에 해당하는, 점으로 구분된 문자열입니다.
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 madepytest에서 patch를 데코레이터로 사용하기
pytest에서 데코레이터로 사용하면 @patch()가 모의 객체를 함수 매개변수로 주입합니다. 검사가 끝나면 모의 객체가 자동으로 제거됩니다.
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()재사용 가능한 모의 응답 만들기
모의 응답 객체를 직접 만들면 코드가 장황해집니다. OpenAI SDK의 응답 구조와 일치하는 올바른 모의 객체를 만들어 주는 도우미 함수를 작성하십시오.
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)
응답에서 도구 호출 모의 처리하기
에이전트의 도구 호출 로직을 검사할 때는 모의 응답에 올바른 구조의 tool_calls 필드가 포함되어야 에이전트의 구문 분석 코드가 이를 올바르게 처리할 수 있습니다.
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)
모의 처리를 위한 pytest fixture
pytest fixture를 사용하면 재사용 가능한 설정 코드를 정의할 수 있습니다. LLM 클라이언트를 패치하고 이를 요청하는 모든 검사에 제공하는 fixture를 만드십시오. 반복해서 작성할 필요가 없습니다.
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()pytest-mock의 모의 도구 fixture
pytest-mock은 패치를 간소화하는 mocker fixture를 제공합니다. 모의 객체를 자동으로 정리하고, 일반적인 unittest.mock.patch보다 깔끔한 구문을 제공합니다.
# 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 itvcr.py로 기록하고 재생하기
vcrpy는 처음 실행할 때 실제 HTTP 상호 작용을 'cassette' 파일에 기록한 다음 이후 실행에서 이를 재생합니다. SDK가 아니라 원시 HTTP API를 사용하는 코드를 검사할 때 이상적입니다.
# 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 None모의 객체가 올바르게 호출되었는지 단언하기
검사가 끝난 후 모의 객체가 올바른 인수와 함께 호출되었는지 확인하십시오. 이를 통해 에이전트가 잘못된 모델을 보내거나, 매개변수를 빠뜨리거나, 잘못된 메시지를 보내는 버그를 발견할 수 있습니다.
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'검사에서 API 오류 시뮬레이션하기
모의 객체가 예외를 발생시키도록 설정하여 LLM 장애를 에이전트가 어떻게 처리하는지 검사하십시오. 실제 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 Noneconftest.py에서 모의 처리용 fixture 구성하기
공유 fixture는 검사 디렉터리의 루트에 있는 conftest.py에 배치하십시오. pytest는 이 파일을 자동으로 검색하고, 가져오기 없이 모든 검사 파일에서 fixture를 사용할 수 있게 합니다.
# 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_search이해도 확인: LLM 호출 모의 처리
에이전트 검사에 사용하는 모의 처리 기법을 제대로 이해했는지 확인해 보십시오.
복습: 검사에서 LLM 호출 모의 처리하기
이제 빠르고 신뢰할 수 있는 에이전트 단위 검사를 작성하는 데 필요한 도구를 갖추었습니다.
unittest.mock.patch()를 사용하여 LLM 클라이언트를 모의 객체로 바꾸십시오- SDK의 응답 구조와 일치하는 재사용 가능한 모의 응답 도우미를 만드십시오
- 올바른 구조의
tool_calls필드를 사용하여 도구 호출을 모의 처리하십시오 - pytest fixture와
conftest.py를 사용하여 여러 검사에서 모의 객체를 공유하십시오 - 더 깔끔한 구문을 위해
pytest-mock을 사용하십시오 vcrpy를 사용하여 실제 HTTP 상호 작용을 기록하고 재생하십시오
모의 객체는 빠르고 유지 관리하기 쉬운 에이전트 검사 모음의 기반입니다.
AI 튜터와 함께 AI Agents을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 60
- 레슨
- 239
자주 묻는 질문
“테스트에서 LLM 호출 모의 처리” 강의는 무료인가요?
네 — “테스트에서 LLM 호출 모의 처리” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Agents 강의 전체를 잠금 해제할 수 있습니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
“테스트에서 LLM 호출 모의 처리”에서 뭘 배우나요?
unittest.mock, pytest 픽스처, LLM 응답 기록 및 재생을 다룹니다. 브라우저에서 직접 실행하는 실습 코드로 AI Agents을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Agents을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Agents은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“테스트에서 LLM 호출 모의 처리” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Agents 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Agents 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 에이전트 테스트가 다른 이유
- 테스트에서 LLM 호출 모의 처리
- 단정문 기반 에이전트 테스트
- 에이전트 파이프라인의 통합 테스트