From harness-claude
Mocks functions, modules, timers, dates, and spies in Vitest and Jest tests to isolate units, control behaviors, verify calls, and test time-dependent code.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Mock modules, functions, and timers in Vitest and Jest to isolate units under test
Guides Vitest unit and integration testing for JavaScript/TypeScript apps using Jest-compatible API, Vite integration, MSW v2 HTTP mocking, vi.mock hoisting, fake timers, snapshots, and test isolation.
Provides TypeScript testing patterns using Vitest for unit tests, MSW for API mocking, typed mocks for dependency injection, and snapshot testing.
Provides Jest testing patterns for unit tests, mocks, spies, snapshots, setup/teardown, and matchers including equality, truthiness, numbers, strings, and arrays.
Share bugs, ideas, or general feedback.
Mock modules, functions, and timers in Vitest and Jest to isolate units under test
vi.fn():import { vi, describe, it, expect } from 'vitest';
const sendEmail = vi.fn();
it('calls sendEmail with correct args', () => {
sendEmail('alice@test.com', 'Welcome');
expect(sendEmail).toHaveBeenCalledWith('alice@test.com', 'Welcome');
expect(sendEmail).toHaveBeenCalledTimes(1);
});
const getUser = vi.fn();
getUser.mockReturnValue({ id: '1', name: 'Alice' });
getUser.mockReturnValueOnce({ id: '2', name: 'Bob' }); // First call only
getUser.mockResolvedValue({ id: '1', name: 'Alice' }); // Async
getUser.mockRejectedValue(new Error('Not found')); // Async error
import { vi, describe, it, expect } from 'vitest';
vi.mock('./email-service', () => ({
sendEmail: vi.fn().mockResolvedValue(true),
}));
import { sendEmail } from './email-service';
import { createUser } from './user-service';
it('sends welcome email on user creation', async () => {
await createUser({ name: 'Alice', email: 'alice@test.com' });
expect(sendEmail).toHaveBeenCalledWith('alice@test.com', expect.stringContaining('Welcome'));
});
const spy = vi.spyOn(console, 'log');
doSomething();
expect(spy).toHaveBeenCalledWith('Processing...');
spy.mockRestore(); // Restore original implementation
it('debounces rapid calls', () => {
vi.useFakeTimers();
const callback = vi.fn();
const debounced = debounce(callback, 300);
debounced();
debounced();
debounced();
expect(callback).not.toHaveBeenCalled();
vi.advanceTimersByTime(300);
expect(callback).toHaveBeenCalledTimes(1);
vi.useRealTimers();
});
it('uses current timestamp', () => {
vi.setSystemTime(new Date('2024-01-15T12:00:00Z'));
const record = createRecord();
expect(record.createdAt).toEqual(new Date('2024-01-15T12:00:00Z'));
vi.useRealTimers();
});
vi.mock('./utils', async () => {
const actual = await vi.importActual('./utils');
return {
...actual,
generateId: vi.fn().mockReturnValue('test-id-123'),
};
});
afterEach(() => {
vi.restoreAllMocks(); // Restores original implementations
// vi.clearAllMocks(); // Clears call history but keeps mock implementation
// vi.resetAllMocks(); // Resets implementation to vi.fn()
});
import type { UserService } from './user-service';
const mockUserService: Pick<UserService, 'findById' | 'create'> = {
findById: vi.fn(),
create: vi.fn(),
};
Mocking replaces real dependencies with controlled substitutes. This isolates the unit under test and lets you control inputs, verify outputs, and simulate error conditions.
Mock vs Spy vs Stub:
vi.fn()) — a fake function that records calls and can return configured valuesvi.spyOn()) — wraps a real function, recording calls while preserving the original behavior (unless overridden)mockReturnValue)Module mocking mechanics: vi.mock() is hoisted to the top of the file by Vitest's transformer. This means it executes before imports, replacing the module before any code uses it. The factory function is lazy — it runs when the module is first imported.
Common matchers for mock assertions:
toHaveBeenCalled() — called at least oncetoHaveBeenCalledTimes(n) — called exactly n timestoHaveBeenCalledWith(arg1, arg2) — called with specific argumentstoHaveBeenLastCalledWith(args) — last call had these argumentsexpect.any(Constructor) — matches any instance of the constructorexpect.stringContaining(str) — matches strings containing the substringTrade-offs:
https://vitest.dev/guide/mocking.html