pytest에서 API Mocking에 지쳐서, 더 깔끔한 방법을 만들었습니다.
Source: Dev.to

Python으로 통합 테스트를 충분히 작성해 보면, 이 벽에 부딪히게 됩니다.
테스트가 세 개의 외부 서비스를 호출합니다.
첫 번째 엔드포인트를 모킹합니다.
그 다음 또 다른 엔드포인트를 모킹합니다.
다시 또 다른 엔드포인트를 모킹합니다.
갑자기 테스트가 60줄이 되고, 그 절반은 패치 코드가 됩니다.
이 시점에서는 행동을 테스트하는 것이 아니라,
구조물을 유지보수하고 있는 겁니다.
서비스‑대‑서비스 흐름을 작업하면서 특히 다음과 같은 경우에 이 문제를 반복해서 겪었습니다.
- 하나의 작업이 여러 HTTP 호출을 트리거할 때
- 서로 다른 테스트가 서로 다른 응답 조합을 필요로 할 때
- 픽스처가 미니 프레임워크처럼 변해 갈 때
툴링 생태계는 강력합니다—responses, unittest.mock, httpx 모킹 유틸리티 등—하지만 엔드포인트 수가 늘어나면 사용성(ergonomics)이 떨어지기 시작합니다.
문제는 기능이 아니라
가독성에 있습니다.
한계점
다음은 멀티 엔드포인트 모킹이 종종 변하는 모습입니다:
import responses
@responses.activate
def test_checkout():
responses.add(
responses.GET,
"https://api.example.com/users/1",
json={"id": 1, "name": "Alice"},
status=200,
)
responses.add(
responses.POST,
"https://api.example.com/orders",
json={"order_id": 42},
status=201,
)
result = checkout_flow()
assert result.success
이것은 동작합니다. 하지만 규모를 키우면:
- 테스트마다 다른 조합
- 조건부 응답
- 동적 페이로드
- 부분 URL 매칭
- 다중 외부 서비스
이제 픽스처가 늘어나고. 헬퍼가 늘어나고. 패치가 퍼지고. 테스트가 인프라가 됩니다.
내가 원했던 것
나는 다음과 같은 것을 원했습니다:
- pytest 내부에 자연스럽게 존재한다
- 목(mock)들을 테스트 로직에 가깝게 유지한다
- 다중 엔드포인트 흐름을 읽기 쉽게 만든다
- 테스트 서버를 띄우는 것을 피한다
- 깊은 패치 트리를 피한다
그래서 api‑mocker 라는 작은 유틸리티를 만들었습니다.
철학은 간단했습니다: 최소한의 표면적. 무거운 DSL도, 프레임워크 추상화도 없습니다. 오직 명시적인 엔드포인트 선언만 있습니다.

예시
def test_checkout_flow(api_mocker):
api_mocker.get("/users/1").respond_with(
status=200,
json={"id": 1, "name": "Alice"},
)
api_mocker.post("/orders").respond_with(
status=201,
json={"order_id": 42},
)
result = checkout_flow()
assert result.success
- 데코레이터 없음.
- 활성화 컨텍스트 없음.
- 흩어진 패치 로직 없음.
픽스처는 각 테스트마다 라이프사이클과 정리를 처리합니다.
디자인 원칙
테스트당 격리
모크는 각 테스트 후 자동으로 리셋됩니다. 공유 상태 누수가 없습니다.
명시적 실패
- 예상된 엔드포인트가 호출되지 않으면 테스트가 실패합니다.
- 예상치 못한 엔드포인트가 호출되면 테스트가 실패합니다.
조용한 성공은 통합 문제를 숨깁니다.
경량 가로채기
내장 서버가 없습니다. 프로세스 오버헤드가 없습니다. 가로채기는 요청 레이어에서 발생합니다.

이 접근 방식이 가장 효과적인 경우
- 마이크로서비스 아키텍처
- 여러 타사 API를 호출하는 서비스
- 결제 또는 인증 흐름
- 오케스트레이터 스타일 백엔드
단일 흐름이 두 개 이상의 HTTP 통합을 다룰 때 어디에서든.
내가 탐구하고 있는 열린 질문들
Mocking 라이브러리는 항상 단순함과 유연성 사이의 긴장을 겪습니다. 현재 활발히 고민하고 있는 영역들:
- 비동기 클라이언트 처리
- 스트리밍 응답
- 모킹이 계약 테스트에 양보해야 할 때
- 대규모 테스트 스위트에서 과도한 모킹 감지
이러한 트레이드오프는 장기적인 테스트 품질에 영향을 미칩니다.

왜 이 글을 공유하는가
Mocking 전략은 코드베이스 건강에 직접적인 영향을 미칩니다.
읽기 쉬운 테스트는 확장됩니다. Fixture 정글은 그렇지 않습니다.
Python에서 복잡한 다중 엔드포인트 통합 테스트를 다뤄본 경험이 있다면, 진심으로 듣고 싶습니다:
- 잘 작동한 점
- 어디서 문제가 발생했는지
- 계약 테스트로 전환한 시점
프로젝트 링크 구현을 살펴보고 싶다면:
- PyPI:
- GitHub:
