PHpullh

PYTHON · 테스트

mock/patch

unittest.mock으로 외부 의존성을 대체하여 단위 테스트를 격리합니다.

테스트중급mockpatch테스트격리

핵심 설명

unittest.mock으로 외부 의존성을 대체하여 단위 테스트를 격리합니다.

Python code

from unittest.mock import Mock, patch, MagicMock

# 기본 Mock
mock_db = Mock()
mock_db.query.return_value = [{"id": 1, "name": "Alice"}]
result = mock_db.query("SELECT * FROM users")
print(f"Mock 결과: {result}")
mock_db.query.assert_called_once_with("SELECT * FROM users")

# side_effect: 동적 반환값
mock_api = Mock()
mock_api.fetch.side_effect = [
    {"status": 200},       # 첫 번째 호출
    {"status": 200},       # 두 번째 호출
    ConnectionError("실패"), # 세 번째 호출
]
print(mock_api.fetch())
print(mock_api.fetch())
try:
    mock_api.fetch()
except ConnectionError as e:
    print(f"예외: {e}")

# patch 데코레이터 패턴
def get_current_time():
    from datetime import datetime
    return datetime.now().isoformat()

# 테스트에서 시간 고정
with patch("datetime.datetime") as mock_dt:
    from datetime import datetime
    mock_dt.now.return_value = datetime(2024, 1, 1, 12, 0)
    # get_current_time() 이 항상 같은 시간 반환

# spec으로 인터페이스 강제
class UserService:
    def get_user(self, user_id: int) -> dict: ...
    def create_user(self, name: str) -> dict: ...

mock_service = Mock(spec=UserService)
mock_service.get_user.return_value = {"name": "Alice"}
print(mock_service.get_user(1))
# mock_service.non_existent()  # AttributeError (spec 위반)

학습 팁

spec=True를 사용하면 Mock이 실제 객체의 인터페이스를 따르게 하여 오타로 인한 테스트 통과를 방지합니다.

주의할 점

너무 많은 것을 Mock하면 테스트가 구현에 결합됩니다. 외부 의존성(DB, API, 파일)만 Mock하세요.

자주 묻는 질문

mock/patch란 무엇인가요?

unittest.mock 으로 외부 의존성을 대체하여 단위 테스트를 격리합니다.

mock/patch 학습 시 주의할 점은 무엇인가요?

너무 많은 것을 Mock하면 테스트가 구현에 결합됩니다. 외부 의존성(DB, API, 파일)만 Mock하세요.