Skip to content
Back to skills

Mocking Strategy

ASecurity

테스트 더블(Mock, Stub, Spy, Fake) 선택과 효과적인 모킹 전략 가이드. '모킹', 'Mock', 'Stub', 'Spy', 'Fake', '테스트 더블', '의존성 격리', '외부 서비스 모킹', 'DB 모킹' 등 테스트 격리 전략 수립 시 이 스킬을 사용한다. unit-tester와 integration-tester의 모킹 설계 역량을 강화한다. 단, 테스트 전략 전체 수립이나 CI 연동은 이 스킬의 범위가 아니다.

  • 1,256 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added May 29, 2026
developmentjavascripttypescriptpythonjavakotlinsqlapi

Works with

  • api

Security analysis

A100/100

Scanned May 29, 2026

npx -y skills add revfactory/harness-100 --skill mocking-strategy --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Mocking Strategy?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Mocking Strategy
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/revfactory-mocking-strategy/badge)](https://www.skillsdirectory.com/skills/revfactory-mocking-strategy)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: mocking-strategy
description: "테스트 더블(Mock, Stub, Spy, Fake) 선택과 효과적인 모킹 전략 가이드. '모킹', 'Mock', 'Stub', 'Spy', 'Fake', '테스트 더블', '의존성 격리', '외부 서비스 모킹', 'DB 모킹' 등 테스트 격리 전략 수립 시 이 스킬을 사용한다. unit-tester와 integration-tester의 모킹 설계 역량을 강화한다. 단, 테스트 전략 전체 수립이나 CI 연동은 이 스킬의 범위가 아니다."
---

# Mocking Strategy — 테스트 더블 선택 및 모킹 전략 가이드

의존성을 효과적으로 격리하여 안정적인 테스트를 만드는 방법론.

## 테스트 더블 유형 비교

| 유형 | 목적 | 동작 | 검증 대상 |
|------|------|------|----------|
| **Dummy** | 파라미터 채움 | 아무것도 안 함 | 사용되지 않음 |
| **Stub** | 고정 응답 제공 | 미리 정의된 값 반환 | 상태(결과값) |
| **Spy** | 호출 기록 | 실제 동작 + 기록 | 상호작용(호출 횟수/인자) |
| **Mock** | 기대 동작 정의 | 기대에 맞으면 통과 | 상호작용(호출 순서/인자) |
| **Fake** | 경량 구현 | 동작하는 간소화 구현 | 상태(통합 수준) |

## 선택 의사결정 트리

```
외부 의존성을 격리해야 한다
├── 응답값만 필요 → Stub
├── 호출 여부/횟수 확인 필요 → Mock 또는 Spy
│   ├── 실제 동작도 필요 → Spy
│   └── 실제 동작 불필요 → Mock
├── 동작하는 경량 구현 필요 → Fake
│   └── 예: InMemoryRepository, FakeEmailSender
└── 그냥 타입만 맞추면 됨 → Dummy
```

## 계층별 모킹 전략

### Repository/DB 계층
```python
# Stub: 고정 데이터 반환
stub_repo = Mock(spec=UserRepository)
stub_repo.find_by_id.return_value = User(id=1, name="테스트")

# Fake: 인메모리 구현
class FakeUserRepository(UserRepository):
    def __init__(self):
        self._store = {}
    def save(self, user):
        self._store[user.id] = user
    def find_by_id(self, id):
        return self._store.get(id)
```

### 외부 API 계층
```python
# HTTP 모킹 (responses / httpx_mock)
@responses.activate
def test_payment_api():
    responses.add(
        responses.POST, "https://api.pg.com/charge",
        json={"status": "success", "tx_id": "TX123"},
        status=200
    )
    result = payment_service.charge(10000)
    assert result.tx_id == "TX123"

# 타임아웃 / 에러 시뮬레이션
responses.add(
    responses.POST, "https://api.pg.com/charge",
    body=ConnectionError("timeout")
)
```

### 메시지 큐 계층
```python
class FakeMessageBroker(MessageBroker):
    def __init__(self):
        self.published = []
    def publish(self, topic, message):
        self.published.append((topic, message))
    def assert_published(self, topic, expected_count=1):
        actual = [m for t, m in self.published if t == topic]
        assert len(actual) == expected_count
```

### 시간/날짜 계층
```python
# 시간 의존성 주입
class OrderService:
    def __init__(self, clock=datetime.now):
        self.clock = clock

# 테스트에서 고정 시간
fixed_time = lambda: datetime(2024, 1, 1, 12, 0, 0)
service = OrderService(clock=fixed_time)
```

## 모킹 안티패턴과 해결

| 안티패턴 | 문제 | 해결 |
|---------|------|------|
| **과도한 모킹** | 구현 상세에 테스트가 결합 | 동작 기반 테스트로 전환 |
| **모킹 사슬** | `mock.a.b.c.d()` 깊은 모킹 | 디미터 법칙 위반 — 코드 리팩토링 |
| **모킹 지옥** | 모든 것을 Mock | Fake로 대체, 통합 테스트 추가 |
| **반복 설정** | 모든 테스트에서 같은 Mock 설정 | Fixture/Builder 패턴 도입 |
| **Mock 검증 과다** | `verify(mock, times(1)).method()` 남용 | 필수 상호작용만 검증 |

## 프레임워크별 모킹 도구

### Python
```python
# unittest.mock
from unittest.mock import Mock, patch, MagicMock
# pytest-mock
def test_something(mocker):
    mocker.patch('module.Class.method', return_value=42)
# responses (HTTP)
# freezegun (시간)
```

### JavaScript/TypeScript
```typescript
// Jest
jest.mock('./userService');
jest.spyOn(service, 'findUser').mockResolvedValue(mockUser);
// MSW (HTTP — 서비스 워커)
server.use(rest.get('/api/users', (req, res, ctx) => res(ctx.json([]))));
// Sinon (범용)
sinon.stub(db, 'query').resolves([]);
```

### Java/Kotlin
```java
// Mockito
@Mock UserRepository repo;
when(repo.findById(1L)).thenReturn(Optional.of(user));
verify(repo, times(1)).save(any(User.class));
// WireMock (HTTP)
// Testcontainers (실제 DB/Redis)
```

## Testcontainers 활용 (Fake 대안)

```python
# 실제 DB를 도커로 격리 — Fake보다 현실적
@pytest.fixture
def postgres():
    with PostgresContainer("postgres:16") as pg:
        engine = create_engine(pg.get_connection_url())
        yield engine

def test_user_crud(postgres):
    # 실제 PostgreSQL에서 테스트
    repo = UserRepository(postgres)
    repo.save(User(name="test"))
    assert repo.find_by_name("test") is not None
```

## 모킹 수준 결정 매트릭스

| 테스트 유형 | DB | 외부 API | 메시지 큐 | 파일 시스템 |
|------------|-----|---------|----------|-----------|
| 단위 테스트 | Stub/Mock | Stub | Mock | Stub |
| 통합 테스트 | Fake/Container | WireMock | Fake | tmpdir |
| E2E 테스트 | 실제 DB | Sandbox API | 실제 큐 | 실제 FS |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…