| name | vitest |
| description | Vitest unit testing patterns for TypeScript. Covers test structure, mocking, assertions, and coverage. Triggers on vitest, describe, it, expect, mock. |
| triggers | vitest, describe, \bit\(, expect, mock, \.test\.ts, \.spec\.ts |
MCPSearch({ query: "select:mcp__plugin_devtools_context7__query-docs" })
// Test patterns
mcp__context7__query_docs({
libraryId: "/vitest-dev/vitest",
query: "How do I use describe, it, expect, and beforeEach?",
});
// Mocking
mcp__context7__query_docs({
libraryId: "/vitest-dev/vitest",
query: "How do I use vi.mock, vi.fn, and vi.spyOn for mocking?",
});
// Async testing
mcp__context7__query_docs({
libraryId: "/vitest-dev/vitest",
query: "How do I test async code with rejects and resolves?",
});
Note: Context7 v2 uses server-side filtering. Use descriptive natural language queries.
| Pattern | Template | Use When |
|---|---|---|
| Service/Unit tests | templates/service-test.ts.md |
Testing classes/functions |
| Module mocking | templates/mock-module.ts.md |
Mocking dependencies |
| Timer mocking | templates/mock-timers.ts.md |
Testing setTimeout/intervals |
Read the templates for scaffolding new tests. Each includes placeholders and examples.
const mockFn = vi.fn();
mockFn.mockReturnValue("mocked");
mockFn.mockResolvedValue("async mocked");
mockFn.mockImplementation((x) => x * 2);
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledWith("arg");
expect(mockFn).toHaveBeenCalledTimes(1);
Mock modules:
vi.mock("./myModule", () => ({
myFunction: vi.fn().mockReturnValue("mocked"),
}));
// Partial mock (keep some real implementations)
vi.mock("./myModule", async () => {
const actual = await vi.importActual("./myModule");
return {
...actual,
specificFunction: vi.fn(),
};
});
Spy on methods:
const spy = vi.spyOn(object, "method");
spy.mockReturnValue("mocked");
// Restore original
spy.mockRestore();
Mock timers:
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
it("handles timeouts", async () => {
const callback = vi.fn();
setTimeout(callback, 1000);
vi.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalled();
});
it("handles dates", () => {
vi.setSystemTime(new Date("2024-01-15"));
expect(new Date().toISOString()).toContain("2024-01-15");
});
Mock environment variables:
beforeEach(() => {
vi.stubEnv("API_KEY", "test-key");
});
afterEach(() => {
vi.unstubAllEnvs();
});
const mockDb = {
query: vi.fn(),
};
// Different responses for different inputs
mockDb.query.mockImplementation((sql: string) => {
if (sql.includes("SELECT")) return Promise.resolve([{ id: 1 }]);
if (sql.includes("INSERT")) return Promise.resolve({ insertId: 1 });
return Promise.reject(new Error("Unknown query"));
});
Mock sequences:
const mockFetch = vi
.fn()
.mockResolvedValueOnce({ status: 500 }) // First call fails
.mockResolvedValueOnce({ status: 200 }); // Retry succeeds
await expect(fetchWithRetry()).resolves.toEqual({ status: 200 });
expect(mockFetch).toHaveBeenCalledTimes(2);
Mock classes:
vi.mock("./EmailService", () => ({
EmailService: vi.fn().mockImplementation(() => ({
send: vi.fn().mockResolvedValue({ sent: true }),
verify: vi.fn().mockResolvedValue(true),
})),
}));
Verify call order:
const mockA = vi.fn();
const mockB = vi.fn();
await service.process(); // Should call A then B
const callOrder = [
...mockA.mock.invocationCallOrder,
...mockB.mock.invocationCallOrder,
];
expect(callOrder).toEqual([1, 2]); // A called first, then B
expect(value).toBe(exact); // ===
expect(value).toEqual(deep); // Deep equality
expect(value).toBeDefined();
expect(value).toBeNull();
expect(value).toBeTruthy();
expect(value).toContain(item);
expect(value).toHaveLength(n);
expect(value).toMatch(/regex/);
// Objects
expect(obj).toHaveProperty("key");
expect(obj).toMatchObject({ partial: true });
// Async
await expect(promise).resolves.toBe(value);
await expect(promise).rejects.toThrow("error");
Naming: Test files=*.test.ts or *.spec.ts
- Context7 docs fetched for current API
- Tests are isolated (no dependencies)
- Mocks used for external services
- Descriptive test names
- Coverage for edge cases