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() // chạy SAU vi.mock bên dưới
vi.mock("@/api/user", () => ({
fetchUser: mockFetchUser, // ReferenceError: Cannot access before initialization
}))Hai cách sửa:
ts
// 1. vi.hoisted: khai biến trong hoisted scope
const { mockFetchUser } = vi.hoisted(() => ({ mockFetchUser: vi.fn() }))
vi.mock("@/api/user", () => ({ fetchUser: mockFetchUser }))
// 2. tạo mock ngay trong factory, lấy ra dùng sau
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ỉ.