PHpullh
학습 라이브러리/Python/pytest 고급 — mock & 비동기 테스트

PYTHON · 테스트

pytest 고급 — mock & 비동기 테스트

unittest.mock으로 외부 의존성을 격리하고 비동기 코드를 테스트합니다.

테스트고급pytest-asyncioAsyncMockMagicMockpatch비동기테스트

핵심 설명

unittest.mock으로 외부 의존성을 격리하고 비동기 코드를 테스트합니다.

Python code

import pytest
from unittest.mock import AsyncMock, MagicMock, patch

# 비동기 함수 테스트 (pytest-asyncio 필요)
# pip install pytest-asyncio

# pytest.ini 또는 pyproject.toml에 추가:
# [tool.pytest.ini_options]
# asyncio_mode = "auto"

async def fetch_user(api_client, user_id: int) -> dict:
    response = await api_client.get(f"/users/{user_id}")
    return response.json()

@pytest.mark.asyncio
async def test_fetch_user():
    mock_client = AsyncMock()
    mock_client.get.return_value.json.return_value = {
        "id": 1, "name": "Alice"
    }

    result = await fetch_user(mock_client, 1)

    mock_client.get.assert_called_once_with("/users/1")
    assert result["name"] == "Alice"

# patch 데코레이터로 의존성 교체
@patch("requests.get")
def test_with_patch(mock_get):
    mock_get.return_value.json.return_value = {"status": "ok"}
    import requests
    resp = requests.get("https://api.example.com")
    assert resp.json()["status"] == "ok"
    mock_get.assert_called_once_with("https://api.example.com")

# fixture + mock 조합
@pytest.fixture
def mock_db():
    db = MagicMock()
    db.find.return_value = [{"id": 1}, {"id": 2}]
    return db

def test_service(mock_db):
    results = mock_db.find({"active": True})
    assert len(results) == 2
    mock_db.find.assert_called_once_with({"active": True})

학습 팁

AsyncMockawait가 가능한 Mock 객체입니다. Python 3.8+에서 기본 제공됩니다.

주의할 점

@patch는 테스트 함수의 인수로 Mock 객체를 전달할 때 데코레이터 순서(아래→위)와 인수 순서(왼→오)가 일치해야 합니다.

자주 묻는 질문

pytest 고급 — mock & 비동기 테스트란 무엇인가요?

unittest.mock 으로 외부 의존성을 격리하고 비동기 코드를 테스트합니다.

pytest 고급 — mock & 비동기 테스트 학습 시 주의할 점은 무엇인가요?

@patch 는 테스트 함수의 인수로 Mock 객체를 전달할 때 데코레이터 순서(아래→위)와 인수 순서(왼→오)가 일치해야 합니다.