파이썬 mock 객체 사용법, 외부 의존성 없이 테스트 격리하는 법
🧪 테스트 격리의 핵심, mock으로 API와 DB 없이도 완벽 테스트!
테스트 코드를 작성하다 보면 외부 시스템과의 연결을 피할 수 없는 경우가 많습니다.
예를 들어, 외부 API를 호출하거나 데이터베이스에 접속하는 코드가 포함된 경우죠.
하지만 이런 외부 요소는 테스트를 느리게 만들고, 때로는 예기치 않게 실패하게 만드는 원인이 됩니다.
그래서 테스트의 독립성과 정확도를 높이기 위해 mock 객체를 활용한 테스트 격리가 매우 중요해졌습니다.
파이썬에서는 unittest.mock 모듈이 이 작업을 간편하게 도와줍니다.
mock 객체를 사용하면 실제로 API나 DB에 연결하지 않고도 동일한 인터페이스를 가진 가짜 객체를 만들어 테스트할 수 있어요.
이번 글에서는 mock이 무엇이고 왜 필요한지, 어떻게 사용하는지에 대해 실전 예제를 통해 자세히 알려드릴게요.
📋 목차
🧱 mock 객체란 무엇인가요?
mock 객체는 테스트 중 실제 동작 대신 가짜로 기능을 흉내 내는 객체를 말합니다.
예를 들어 외부 서버에 요청을 보내는 함수를 테스트하려 할 때, 진짜 요청을 보내는 대신 응답을 미리 정의해놓은 mock 객체를 사용하면 테스트의 안정성과 속도가 크게 향상됩니다.
파이썬의 unittest.mock 모듈은 Mock, patch, MagicMock 등의 도구를 제공하여 다양한 방식으로 객체를 대체할 수 있도록 돕습니다.
이러한 mock은 단순히 리턴 값을 지정하는 것뿐 아니라, 호출 횟수, 호출 인자, 예외 발생 시나리오까지 테스트할 수 있는 강력한 기능을 가지고 있어요.
💎 핵심 포인트:
mock은 외부 의존성을 제거하고, 테스트를 격리하여 더 빠르고 안정적으로 만드는 테스트 전략입니다.
- 🧪실제 호출 없이도 테스트 가능하다는 점이 가장 큰 장점입니다
- ⏱️mock을 쓰면 네트워크, 파일, DB 지연 없이 빠른 테스트 가능
- 🧰mock 객체는
.return_value,.side_effect등 다양한 옵션 지원
즉, mock 객체는 테스트의 독립성과 효율성을 높이기 위한 필수 도구이며, 실제 운영 환경을 흉내 내는 데 매우 효과적입니다.
이제 다음 단계에서는 외부 API를 어떻게 mock으로 대체하는지 살펴보겠습니다.
🔌 외부 API 대신 mock 사용하기
실제 웹 API는 네트워크 상태, 서버 오류, 요금 문제 등 다양한 이유로 테스트에 불안정한 요소가 될 수 있습니다.
따라서 외부 API를 호출하는 코드를 테스트할 때는 mock 객체로 대체하여 테스트를 격리하는 것이 안정적입니다.
파이썬의 unittest.mock에서는 patch()를 사용해 외부 API 함수나 메서드를 일시적으로 바꿔치기할 수 있습니다.
이로 인해 실제 HTTP 요청 없이도 예상된 결과를 리턴하도록 설정할 수 있고, API 응답에 따른 분기 처리도 자유롭게 테스트할 수 있습니다.
import requests
from unittest.mock import patch
def fetch_data():
response = requests.get("https://api.example.com/data")
return response.json()
def test_fetch_data():
with patch("requests.get") as mock_get:
mock_get.return_value.json.return_value = {"value": 42}
result = fetch_data()
assert result["value"] == 42
- 🧪
patch()는 외부 모듈 함수나 클래스, 메서드를 임시로 대체합니다 - 📡실제 API 호출 없이도 예상된 응답을 시뮬레이션할 수 있습니다
- 🧰복잡한 외부 API 테스트도 빠르고 안정적으로 수행할 수 있습니다
mock을 사용하면 API 응답을 다양하게 구성해 성공, 실패, 예외 상황까지 모두 테스트할 수 있습니다.
실제 요청 없이도 정확한 테스트를 구현할 수 있다는 점이 가장 큰 장점입니다.
📁 DB 연결 없이 테스트하는 방법
데이터베이스는 테스트를 느리게 만들고, 외부 상태에 따라 예기치 않게 실패할 수 있는 대표적인 외부 요소입니다.
이 때문에 DB와 연동되는 함수나 메서드를 테스트할 때는 mock 객체로 데이터베이스 동작을 흉내 내는 것이 훨씬 안전하고 효율적입니다.
특히 ORM(Object Relational Mapping)이나 커넥션 객체, 쿼리 메서드 등을 patch()로 감싸주면 DB에 연결하지 않고도 원하는 데이터 흐름을 시뮬레이션할 수 있습니다.
테스트가 실제 DB를 건드리지 않기 때문에, 테스트 실행 속도와 데이터 무결성을 모두 확보할 수 있죠.
from unittest.mock import patch
class UserRepository:
def get_user_by_id(self, user_id):
# 실제로는 DB 쿼리
...
def test_get_user_by_id():
with patch.object(UserRepository, 'get_user_by_id', return_value={"id": 1, "name": "Alice"}):
repo = UserRepository()
result = repo.get_user_by_id(1)
assert result["name"] == "Alice"
- 📁DB 연동 메서드는
patch.object()로 클래스 내부 메서드를 대체 - 🧪DB 없이도 원하는 데이터 흐름을 정확하게 재현할 수 있음
- 🚀테스트 속도가 빨라지고 데이터 충돌 위험도 사라짐
이처럼 mock을 활용하면 DB가 실제로 없어도 전체 로직을 검증할 수 있어, CI/CD 환경이나 빠른 테스트 반복이 필요한 상황에서 특히 유용합니다.
🧪 return_value와 side_effect의 활용
mock 객체를 사용할 때 가장 많이 쓰이는 속성이 return_value와 side_effect입니다.
이 두 가지는 단순한 반환값 설정을 넘어서, 다양한 테스트 시나리오를 만들 수 있는 핵심 기능입니다.
return_value는 호출 시 고정된 값을 반환하도록 설정하며, side_effect는 함수처럼 동작하거나 예외를 발생시킬 수도 있습니다.
즉, 조건별로 다른 동작을 유도하거나 실패 케이스를 테스트할 때 매우 유용하죠.
💎 핵심 포인트:
return_value는 고정된 응답을 설정하고, side_effect는 함수처럼 동작하거나 예외를 발생시키는 데 사용됩니다.
from unittest.mock import Mock
# return_value 사용
mock_api = Mock()
mock_api.get_data.return_value = {"status": "ok"}
print(mock_api.get_data()) # {'status': 'ok'}
# side_effect로 예외 발생
mock_api.get_data.side_effect = ValueError("API 오류 발생")
try:
mock_api.get_data()
except ValueError as e:
print(e) # API 오류 발생
- 🔁return_value는 단일 응답을 고정적으로 반환
- ⚡side_effect는 함수, 예외, 리스트 등 다양한 방식으로 작동
- 🧠복잡한 흐름을 미리 설정해 테스트 시나리오 다양화 가능
이 기능들을 활용하면 mock 객체가 단순 응답자에 그치지 않고, 유연한 테스트 도구로 진화하게 됩니다.
다음으로는 실무에서 자주 쓰이는 mock 패턴을 정리해 보겠습니다.
💡 실전에서 자주 쓰는 mock 패턴
mock 객체는 테스트 자동화에서 매우 자주 사용되기 때문에, 실무에서는 반복적으로 쓰이는 패턴들이 자연스럽게 정리되어 왔습니다.
여기서는 자주 쓰이는 5가지 mock 활용 방식을 간단한 예제와 함께 소개할게요.
- 🧱기본 Mock 객체 생성 후 return_value 설정하기
- 🔁side_effect로 예외 발생이나 동적 리턴 처리
- 🔄patch()로 외부 모듈 함수 임시 대체
- 🏗️patch.object()로 클래스 내부 메서드 변경
- 📊assert_called_with()로 mock 호출 인자 검증
💎 핵심 포인트:
mock 객체는 단순히 리턴 값을 주는 것에 그치지 않고, 호출 여부나 인자까지 확인할 수 있어 테스트의 정확성을 크게 높여줍니다.
이러한 패턴을 익혀두면 테스트 코드를 더 빠르게 작성하고, 협업 시 다른 개발자와의 소통도 훨씬 수월해집니다.
mock은 선택이 아닌 필수 도구임을 기억하세요.
❓ 자주 묻는 질문 (FAQ)
mock과 stub은 어떻게 다른가요?
실제 테스트에서는 mock이 더 자주 사용됩니다.
patch와 patch.object는 언제 쓰나요?
mock 객체의 호출 횟수를 검증할 수 있나요?
mock을 남용하면 안 좋은 점도 있나요?
중요한 로직은 실제 구현과 함께 테스트하는 것이 좋습니다.
side_effect는 어떤 경우에 유용한가요?
복잡한 흐름이나 조건 분기에 따라 다른 응답을 테스트할 때 자주 활용됩니다.
mock으로 속도 개선이 어느 정도 되나요?
특히 대량 테스트나 CI 환경에서 시간 절약 효과가 큽니다.
mock된 함수가 실제로 호출됐는지 어떻게 알 수 있나요?
mock 테스트는 실제 테스트와 병행할 수 있나요?
🧰 mock 객체로 테스트 품질과 효율 모두 잡기
파이썬에서 unittest.mock 모듈은 테스트 자동화의 핵심 도구로 자리 잡고 있습니다.
외부 API나 데이터베이스 없이도 테스트를 수행할 수 있도록 도와주는 mock 객체는, 테스트의 속도, 안정성, 정확도 모두를 높여주는 역할을 합니다.
이번 글에서는 mock이 왜 필요한지부터 시작해, 외부 API 대체, DB 연결 제거, 다양한 패턴 활용까지 실무에 바로 적용할 수 있는 내용을 정리해보았습니다.
return_value와 side_effect 등 세부 옵션까지 이해하면 복잡한 테스트도 훨씬 간결하게 구현할 수 있습니다.
테스트 코드를 개선하고 싶거나, 불안정한 외부 요소 때문에 테스트가 잦은 오류를 낼 때는 mock 객체를 적극 도입해보세요.
빠르고 유연한 테스트 환경이 개발 효율을 얼마나 높이는지 직접 체감하실 수 있을 거예요.
🏷️ 관련 태그 : 파이썬테스트, mock객체, unittest, pytest, 테스트자동화, 파이썬모킹, 외부API모킹, DB테스트제거, 테스트격리, side_effect