Claude-skill-registry http-mocking
HTTP mocking with nock - the only allowed mocking library
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/http-mocking" ~/.claude/skills/majiayu000-claude-skill-registry-http-mocking && rm -rf "$T"
manifest:
skills/data/http-mocking/SKILL.mdsource content
Nock HTTP Mocking Patterns
Critical Rule: ONLY nock for HTTP Mocking
This is a CRITICAL rule that MUST be enforced:
✅ ONLY
is allowed for HTTP mocking
❌ NEVER use nock
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)