mocking-strategies — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited mocking-strategies (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Mocking isolates the code under test from its dependencies. Done right, mocks make tests fast and focused. Done wrong, they create brittle tests coupled to implementation details.
| Type | Purpose | Verifies Calls? | Returns Data? |
|---|---|---|---|
| Stub | Replace with canned response | No | Yes |
| Spy | Observe calls without replacing | Yes | Original |
| Mock | Replace + verify calls + canned response | Yes | Yes |
// STUB: Replace function, return fixed data
const getUser = vi.fn().mockResolvedValue({ id: 1, name: 'Alice' })
// SPY: Watch real function, keep original behavior
const spy = vi.spyOn(userService, 'getUser')
// Real getUser still runs, but calls are recorded
// MOCK: Replace function, return fixed data, verify calls
const sendEmail = vi.fn().mockResolvedValue({ sent: true })
await notifyUser(1)
expect(sendEmail).toHaveBeenCalledWith('[email protected]', expect.any(String))Module mock:
import { describe, it, expect, vi } from 'vitest'
import { processOrder } from './orders'
// Mock the entire payment module
vi.mock('./payment', () => ({
chargeCard: vi.fn().mockResolvedValue({ success: true, txId: 'tx-123' }),
}))
import { chargeCard } from './payment'
describe('processOrder', () => {
it('charges the card and returns order confirmation', async () => {
const order = await processOrder({ userId: 1, amount: 99 })
expect(chargeCard).toHaveBeenCalledWith({ userId: 1, amount: 99 })
expect(order.status).toBe('confirmed')
expect(order.transactionId).toBe('tx-123')
})
it('handles payment failure', async () => {
vi.mocked(chargeCard).mockRejectedValueOnce(new Error('Card declined'))
await expect(processOrder({ userId: 1, amount: 99 }))
.rejects.toThrow('Card declined')
})
})Spy on object method:
const spy = vi.spyOn(console, 'error').mockImplementation(() => {})
await riskyOperation()
expect(spy).toHaveBeenCalledWith('Operation failed:', expect.any(Error))
spy.mockRestore()Patching with context manager:
from unittest.mock import patch, MagicMock
def test_send_notification():
with patch('myapp.services.email.send') as mock_send:
mock_send.return_value = {"sent": True}
result = notify_user(user_id=1, message="Hello")
mock_send.assert_called_once_with(
to="[email protected]",
body="Hello"
)
assert result["sent"] is TruePatching with decorator:
@patch('myapp.services.payment.charge_card')
def test_process_order(mock_charge):
mock_charge.return_value = {"success": True, "tx_id": "tx-123"}
order = process_order(user_id=1, amount=99)
mock_charge.assert_called_once_with(user_id=1, amount=99)
assert order["status"] == "confirmed"Mock side effects for error testing:
@patch('myapp.services.payment.charge_card')
def test_payment_failure(mock_charge):
mock_charge.side_effect = PaymentError("Card declined")
with pytest.raises(PaymentError, match="Card declined"):
process_order(user_id=1, amount=99)Design code to accept dependencies, making them mockable:
// HARD TO TEST: Direct import
import { db } from './database'
export async function getUser(id: string) {
return db.query('SELECT * FROM users WHERE id = $1', [id])
}
// EASY TO TEST: Dependency injection
export function createUserService(db: Database) {
return {
async getUser(id: string) {
return db.query('SELECT * FROM users WHERE id = $1', [id])
},
}
}
// In tests:
const mockDb = { query: vi.fn().mockResolvedValue({ id: '1', name: 'Alice' }) }
const service = createUserService(mockDb)
const user = await service.getUser('1')Do not mock these — use the real thing:
1. Pure functions (no side effects, deterministic)
createSlug('Hello World') -> test with real input/output
2. Value objects and data transformations
formatDate(date) -> test with real dates
3. Your own code under test
Do not mock the function you are testing
4. Standard library / language built-ins
Do not mock Array.map, string methods, Math.random (seed instead)
5. Simple internal utilities
If formatCurrency() is fast and pure, call it for realMock only at system boundaries:
For time-dependent code, use fake timers instead of mocking Date:
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'
describe('session expiry', () => {
beforeEach(() => {
vi.useFakeTimers()
})
afterEach(() => {
vi.useRealTimers()
})
it('expires session after 30 minutes', () => {
const session = createSession()
expect(session.isValid()).toBe(true)
vi.advanceTimersByTime(30 * 60 * 1000) // 30 minutes
expect(session.isValid()).toBe(false)
})
})expect(mock).toHaveBeenCalled() without asserting the result tests that you called a mock, not that your code works. Always assert on output or observable behavior.mockRestore() or afterEach(() => vi.restoreAllMocks()) leaks mock state between tests, causing flaky failures.| Scenario | Strategy |
|---|---|
| External API call | Mock the HTTP client |
| Database query | Mock the repository/query function |
| Time-dependent logic | Fake timers (vi.useFakeTimers()) |
| Error paths | mockRejectedValue / side_effect |
| Pure functions | Do NOT mock — test with real input |
| Internal utilities | Do NOT mock — call for real |
| File I/O | Mock the fs calls or use temp directory |
Mock at boundaries: External services, databases, filesystem, network. Do not mock: Pure functions, value objects, the code under test itself. Always restore: vi.restoreAllMocks() in afterEach or use mockRestore(). DI for testability: Accept dependencies as parameters, not hard imports.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.