
http-mocking
by zerobias-org
SKILL.md
name: http-mocking description: HTTP mocking with nock - the only allowed mocking library
Nock HTTP Mocking Patterns
Critical Rule: ONLY nock for HTTP Mocking
This is a CRITICAL rule that MUST be enforced:
✅ ONLY nock is allowed for HTTP mocking
❌ NEVER use jest.mock, sinon, or fetch-mock
See failure-conditions skill Rule 4 for enforcement.
Core Principles
- Mock at HTTP level - Mock the network request, not internal methods
- Match requests accurately - Include method, path, headers, query params
- Return realistic responses - Use response formats matching real API
- Clean up after tests - Use
afterEach(() => nock.cleanAll()) - Verify mocks called - Assert
expect(nock.isDone()).toBe(true)
Basic HTTP Mock Pattern
import nock from 'nock';
describe('WebhookProducer', () => {
afterEach(() => {
nock.cleanAll(); // Clean up after each test
});
it('should list webhooks successfully', async () => {
// Mock the HTTP request
nock('https://api.github.com')
.get('/repos/octocat/Hello-World/hooks')
.reply(200, [
{
id: '12345678',
name: 'web',
active: true,
events: ['push', 'pull_request'],
config: {
url: 'https://example.com/webhook',
content_type: 'json'
},
created_at: '2024-01-01T00:00:00Z'
}
]);
// Execute the test
const producer = new WebhookProducer(httpClient);
const webhooks = await producer.list('octocat', 'Hello-World');
// Assertions
expect(webhooks).toHaveLength(1);
expect(webhooks[0].id).toBeDefined();
expect(nock.isDone()).toBe(true); // Verify mock was called
});
});
Mock with Request Headers
nock('https://api.github.com', {
reqheaders: {
'Authorization': 'Bearer test-token',
'Accept': 'application/vnd.github.v3+json'
}
})
.get('/repos/octocat/Hello-World/hooks')
.reply(200, mockData);
Mock Error Responses
it('should handle 404 error', async () => {
nock('https://api.github.com')
.get('/repos/octocat/Hello-World/hooks/999')
.reply(404, {
message: 'Not Found',
documentation_url: 'https://docs.github.com/rest'
});
// Test error handling
await expect(
producer.get('octocat', 'Hello-World', '999')
).rejects.toThrow(ResourceNotFoundError);
expect(nock.isDone()).toBe(true);
});
Mock POST Request
it('should create webhook', async () => {
const requestBody = {
name: 'web',
config: {
url: 'https://example.com/webhook',
content_type: 'json'
},
events: ['push'],
active: true
};
nock('https://api.github.com')
.post('/repos/octocat/Hello-World/hooks', requestBody)
.reply(201, {
id: '12345678',
...requestBody,
created_at: '2024-01-01T00:00:00Z'
});
const webhook = await producer.create('octocat', 'Hello-World', config);
expect(webhook.id).toBeDefined();
expect(nock.isDone()).toBe(true);
});
Mock with Query Parameters
nock('https://api.github.com')
.get('/repos/octocat/Hello-World/hooks')
.query({ per_page: 20, page: 1 })
.reply(200, mockData);
Reusable Mock Fixtures
// test/fixtures/webhookMocks.ts
export const mockWebhookResponse = {
id: '12345678',
name: 'web',
active: true,
events: ['push', 'pull_request'],
config: {
url: 'https://example.com/webhook',
content_type: 'json'
},
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z'
};
export function mockListWebhooks(owner: string, repo: string, data: any[]) {
return nock('https://api.github.com')
.get(`/repos/${owner}/${repo}/hooks`)
.reply(200, data);
}
Validation Checklist
# Verify ONLY nock is used
grep "from ['\"]nock['\"]" test/unit/*.ts
# Should show nock imports
# Ensure NO forbidden mocking libraries
grep -E "jest\.mock|sinon|fetch-mock" test/*.ts
# Should return nothing (exit code 1)
# Verify mock cleanup present
grep "nock.cleanAll()" test/unit/*.ts
# Should show in afterEach blocks
# Verify mock verification present
grep "nock.isDone()" test/unit/*.ts
# Should show in test assertions
Anti-Patterns: What NOT to Do
❌ WRONG: Using jest.mock
// ❌ NO! Don't mock at method level
jest.mock('./WebhookProducer');
Why wrong: Mocks internal implementation instead of HTTP layer.
❌ WRONG: Using sinon
// ❌ NO! Don't use sinon
import sinon from 'sinon';
const stub = sinon.stub(producer, 'list');
Why wrong: Not allowed - violates testing rules.
❌ WRONG: Using fetch-mock
// ❌ NO! Use nock instead
import fetchMock from 'fetch-mock';
Why wrong: Not allowed - only nock is permitted.
✅ CORRECT: Using nock
// ✅ YES! Mock at HTTP level with nock
import nock from 'nock';
nock('https://api.github.com')
.get('/repos/octocat/Hello-World/hooks')
.reply(200, mockData);
Why correct: Mocks at HTTP level using approved library.
Standard Output Format
When documenting HTTP mocking strategy:
# HTTP Mocking Strategy: {ProducerName}
## Mock Library
✅ **nock** (ONLY allowed library)
## Mock Patterns Created
### List Operation
```typescript
nock('https://api.github.com')
.get('/repos/octocat/Hello-World/hooks')
.reply(200, [mockWebhookResponse]);
Get Operation
nock('https://api.github.com')
.get('/repos/octocat/Hello-World/hooks/12345678')
.reply(200, mockWebhookResponse);
Error Case
nock('https://api.github.com')
.get('/repos/octocat/Hello-World/hooks/999')
.reply(404, { message: 'Not Found' });
Mock Cleanup
✅ afterEach(() => nock.cleanAll())
Mock Verification
✅ expect(nock.isDone()).toBe(true)
Validation
✅ Only nock used ✅ HTTP level mocking ✅ Realistic responses ✅ Proper cleanup ✅ Mock verification
## Success Criteria
HTTP mocking implementation MUST meet all criteria:
- ✅ Only nock library used (no jest.mock, sinon, fetch-mock)
- ✅ All HTTP requests mocked at network level
- ✅ Realistic mock responses (match API format)
- ✅ Proper cleanup after tests (`nock.cleanAll()`)
- ✅ Mock verification in tests (`nock.isDone()`)
- ✅ Reusable mock patterns/fixtures where appropriate
- ✅ Request matching includes method, path, headers (when relevant)
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon