
파이썬 비동기 함수 Mocking, 더 이상 어렵지 않아요!
오늘은 파이썬 (Python)에서 비동기 함수를 Mocking (모킹)하는 방법에 대해 쉽게 설명해 드리려고 해요.
비동기 프로그래밍 코드를 짤 때 유닛 테스트 (unit test) 때문에 골치 아팠던 경험, 다들 한 번쯤 있으시죠?
특히 외부 시스템에 의존하는 비동기 함수는 테스트하기가 정말 까다로운데요.
이럴 때 Mocking (모킹)을 사용하면 복잡한 문제도 깔끔하게 해결할 수 있습니다.
- 왜 비동기 함수를 Mocking (모킹)해야 할까요?
Mocking (모킹)은 테스트를 할 때 꼭 필요한 기술인데요, 특히 비동기 함수 테스트에서는 더더욱 중요합니다.
Mocking (모킹)을 하면 어떤 점이 좋을까요?
- 격리 (Isolation): Mocking (모킹)을 사용하면 테스트 대상 코드만 딱 떼어내서 테스트할 수 있어요. 외부 시스템에 연결하거나 데이터베이스에 접속하는 부분을 Mocking (모킹)으로 대체하면, 테스트가 외부 환경에 영향을 받지 않고 오직 코드 로직에만 집중할 수 있습니다. 마치 우리 집 마당에서만 놀 수 있도록 놀이터를 만들어주는 것과 같아요.
- 성능 (Performance): Mocking (모킹)을 사용하면 느려터진 I/O (입출력) 작업을 생략할 수 있어서 테스트 속도가 엄청나게 빨라집니다. 실제 네트워크 통신이나 데이터베이스 쿼리 (query) 대신 Mocking (모킹)으로 가짜 응답을 만들어주면 순식간에 테스트가 끝나요. 마라톤 대신 100미터 달리기를 하는 것처럼 순식간에 끝낼 수 있죠.
- 결정성 (Determinism): 외부 시스템은 예측 불가능하게 동작할 때가 많아요. 네트워크가 불안정하거나, 데이터베이스 상태가 갑자기 바뀔 수도 있고요. Mocking (모킹)을 사용하면 외부 의존성으로 인한 테스트 불안정성을 없앨 수 있습니다. 언제나 똑같은 환경에서 테스트를 실행할 수 있으니, 테스트 결과가 예측 가능하고 믿을 만해지는 거죠. 마치 매일 똑같은 시간에 해가 뜨는 것처럼 테스트 결과도 항상 예측 가능하게 만들 수 있습니다.
- 비동기 함수 Mocking (모킹) 도구
파이썬 (Python)의 unittest.mock
모듈은 Mocking (모킹)에 필요한 여러 가지 도구를 제공하는데요.
파이썬 (Python) 3.8 버전 이상부터는 AsyncMock
이라는 아주 편리한 도구를 사용해서 비동기 함수를 Mocking (모킹)할 수 있습니다.
만약 파이썬 (Python) 3.8 이전 버전을 사용하고 있다면 MagicMock
을 사용해서 비동기 함수를 Mocking (모킹)해야 합니다.
핵심 요약:
- Mocking (모킹)으로 외부 의존성을 제거하면 테스트 격리, 성능 향상, 결정성 확보가 가능합니다.
- 파이썬 (Python) 3.8 이상에서는
AsyncMock
을 사용해서 비동기 함수를 Mocking (모킹)하는 것을 추천합니다. - Mocking (모킹)을 너무 많이 사용하면 오히려 테스트가 깨지기 쉽고, 코드를 이해하기 어려워질 수 있으니 적절하게 사용하는 것이 중요합니다.
- AsyncMock으로 비동기 함수 Mocking (모킹)하는 방법
AsyncMock
을 사용해서 비동기 함수를 Mocking (모킹)하는 방법을 단계별로 자세히 알아볼까요?
import unittest
from unittest.mock import AsyncMock, patch
# 테스트할 함수
def process_data(data_fetcher):
async def wrapper():
data = await data_fetcher()
return f"Processed: {data}"
return wrapper
class TestProcessData(unittest.TestCase):
@patch("path.to.data_fetcher", new_callable=AsyncMock) # AsyncMock으로 Mocking (모킹)
def test_process_data(self, mock_fetcher):
# Mocking (모킹) 객체가 특정 값을 반환하도록 설정
mock_fetcher.return_value = "Mocked Data" # "Mocked Data" 반환
# 함수 테스트
async def test_logic():
result = await process_data(mock_fetcher)()
self.assertEqual(result, "Processed: Mocked Data") # 결과 값 확인
# 비동기 테스트 실행
import asyncio
asyncio.run(test_logic()) # asyncio.run으로 이벤트 루프 (event loop) 안에서 테스트 실행
if __name__ == "__main__":
unittest.main()
핵심 포인트:
- 비동기 함수를
patch
할 때는new_callable=AsyncMock
옵션을 꼭 넣어줘야 합니다. 그래야AsyncMock
으로 Mocking (모킹)이 됩니다. .return_value
속성을 사용해서 Mocking (모킹) 객체가 반환할 값을 설정할 수 있습니다.mock_fetcher.return_value = "Mocked Data"
이렇게 설정하면mock_fetcher()
를 호출했을 때"Mocked Data"
가 반환됩니다.- 비동기 로직을 테스트하려면 테스트 함수를 이벤트 루프 (event loop) 안에서 실행해야 합니다.
asyncio.run(test_logic())
처럼asyncio.run()
으로 감싸서 실행하면 됩니다.
- MagicMock으로 옛날 파이썬 (Python) 버전에서 Mocking (모킹)하는 방법
파이썬 (Python) 3.8 이전 버전을 사용하고 있다면 AsyncMock
대신 MagicMock
을 사용해야 하는데요.
MagicMock
으로 비동기 함수를 흉내내는 방법은 다음과 같습니다.
from unittest.mock import MagicMock
# MagicMock으로 비동기 함수 Mocking (모킹)
mock_fetcher = MagicMock()
mock_fetcher.return_value = "Mocked Data"
mock_fetcher.__aenter__.return_value = "Mocked Data" # __aenter__ 속성도 설정
async def test():
result = await mock_fetcher()
print(result) # Output: Mocked Data
import asyncio
asyncio.run(test())
MagicMock
을 사용할 수도 있지만, AsyncMock
보다는 직관적이지 않고 기능도 좀 떨어집니다.
그래서 파이썬 (Python) 3.8 이상 버전을 사용하신다면 AsyncMock
을 사용하는 것을 훨씬 더 추천합니다.
- 주의사항
- 언제 Mocking (모킹)해야 할까요?: Mocking (모킹)은 꼭 필요한 경우에만, 그리고 테스트 대상에서 외부 시스템과의 의존성만 끊어낼 때 사용하는 것이 좋습니다. Mocking (모킹)을 너무 많이 사용하면 테스트 코드가 오히려 복잡해지고, 테스트의 의미도 불분명해질 수 있습니다. 정말 필요할 때만 Mocking (모킹)을 사용해주세요.
- Mocking (모킹) 대신 다른 방법은 없을까요?: Mocking (모킹) 대신 실제 의존성 대신 사용할 수 있는 가벼운 대체재 (in-memory database (인메모리 데이터베이스)나 fake object (페이크 객체) 같은 것)를 사용하는 것을 고려해볼 수도 있습니다. Mocking (모킹)이 능사는 아니니까요.
- 테스트 가독성: Mocking (모킹) 설정과 테스트 코드가 명확하고 이해하기 쉽게 작성되었는지 꼭 확인해야 합니다. Mocking (모킹) 설정이 너무 복잡하면 테스트 코드를 읽는 사람이 테스트의 목적을 제대로 파악하기 어려울 수 있어요. 테스트 코드는 최대한 명확하고 간결하게 작성하는 것이 중요합니다.
결론
파이썬 (Python)에서 비동기 함수 Mocking (모킹), 이제 어렵지 않겠죠?
AsyncMock
을 사용하면 파이썬 (Python) 3.8+ 버전에서 비동기 코드를 훨씬 효율적으로 테스트할 수 있습니다.
혹시 파이썬 (Python) 3.8 이전 버전을 사용하고 있다면 MagicMock
을 사용해서 비슷한 효과를 낼 수 있고요.
'Python' 카테고리의 다른 글
파이썬 데코레이터 활용법: 로깅부터 권한 검증까지 완벽 가이드 (0) | 2025.03.24 |
---|---|
파이썬 PDF (Portable Document Format) 처리, Fitz (PyMuPDF) 하나면 끝! (0) | 2025.03.22 |
Python tile-tools 시작하기: Mapbox 타일 작업, 이제 어렵지 않아요! (1) | 2025.03.22 |
파이썬 Switch 문, 이제 이렇게 쓰세요! (2025년 최신 가이드) - Switch Case 완벽 예제 (0) | 2025.03.22 |
FastAPI 핵심 탐구: Starlette 깊이 파헤쳐보기 (0) | 2025.03.22 |