vi.mock (và jest.mock) được hoist lên đầu file, chạy trước mọi import và mọi khai báo biến.
Đó là điều kiện bắt buộc để module thật không kịp được nạp.
ts
const mockFetchUser = vi.fn() // runs AFTER the vi.mock below
vi.mock("@/api/user", () => ({
fetchUser: mockFetchUser, // ReferenceError: Cannot access before initialization
}))Hai cách sửa:
ts
// 1. vi.hoisted: declare the variable in the hoisted scope
const { mockFetchUser } = vi.hoisted(() => ({ mockFetchUser: vi.fn() }))
vi.mock("@/api/user", () => ({ fetchUser: mockFetchUser }))
// 2. create the mock inside the factory, grab it later
vi.mock("@/api/user", () => ({ fetchUser: vi.fn() }))
import { fetchUser } from "@/api/user"
vi.mocked(fetchUser).mockResolvedValue({ id: 1 })Với Jest, quy ước là đặt tên biến bắt đầu bằng mock (mockFetchUser) — Babel plugin cho phép biến theo tiền tố đó lọt qua kiểm tra hoisting; hoặc dùng jest.mock với factory tự tạo jest.fn() bên trong.
Lưu ý thêm: vi.mock chỉ áp cho module path đúng như lúc import, và mock được đăng ký theo file test. Nhớ vi.resetAllMocks() (hoặc restoreMocks: true trong config) giữa các test để implementation không rò rỉ.