Atlas / Skills / revfactory / Mocking Strategy

Mocking StrategySAFE

skills/revfactory/mocking-strategy
Verdict
SAFE
Grade
B
Trust score
89 /100
Version
—
Hosts
—
License
Apache-2.0
Stars
1,297
01

Overview

An agent skill published by revfactory.

Read from source at commit 459e1bb8f76eOBSERVED · 2026-10-12
02

What it tells the agent

The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.

---
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 |
03

Trust audit

SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeNA
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
none-observed
Network
none-observed
Shell
none-observed
Dependencies
pinned
Secrets in source
none-found

Findings (0)

No findings outside the package's declared scope.

Gates applied: no_behavioural_pass.

Audited 2026-10-12 · audit v0.4.1 · source sha 459e1bb8f76efull audit observations/trust-audit/skill/revfactory__mocking-strategy.json · Report an issue / request a re-scan
04

Audit history

Every audit this skill has had.

DateSourceVerdictGradeScoreChange
2026-10-12459e1bb8f76eSAFEB89first audit
05

Questions

Is Mocking Strategy safe to install?

The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.

What can Mocking Strategy access on my machine?

The audit observed no filesystem, network or shell use at all in its source.

How current is this page?

The grade is for one exact copy of the source (459e1bb8f76e), read on 2026-10-12. The repository is watched, and a new audit runs when it changes — this is the first audit.

Advertisement