vitest-5-0-0-16-b
Claude Code's read-only tools, web search on, ludion sync on
Question
Vitest throws when I call vi.mock inside beforeEach. Why?
Answer key
- A correct answer says
- Calling hoisted methods such as vi.mock outside the module's top level now throws an error.
- The stale answer
- vi.mock inside a function or block only warns and is still hoisted.
Answer
`vi.mock` isn't a normal runtime call. Vitest moves it to the top of the test file at compile time, before any `import` runs, so the module is already swapped out when your code imports it. That only works when `vi.mock` is written at the top level of the file. Inside `beforeEach`, the mock would only register after the module had been imported, so it couldn't affect it. Recent Vitest versions warn about `vi.mock` calls that aren't at the top level, and a stricter version turns that into an error, which is probably what you're seeing. I haven't checked the exact behaviour in your installed vitest 5.0.3, and the project's lessons file doesn't mention it.
To fix it, use one of these:
- **Mock once, reset per test:** put `vi.mock('./mod')` at the top level. Then in `beforeEach`, set up what each test needs with `vi.mocked(fn).mockReturnValue(...)` and clear it with `vi.resetAllMocks()`.
- **Mock at runtime:** use `vi.doMock('./mod', factory)`, which isn't moved to the top. Then load the module with `await import('./mod')` after that call, and call `vi.resetModules()` between tests.Grade
wrong
The judge's reason: It says recent Vitest versions only warn about non-top-level vi.mock, which is the stale behavior, and it hedges the throw as coming from some unspecified stricter version instead of stating that Vitest now throws.
Session log
Agent
`vi.mock` isn't a normal runtime call. Vitest moves it to the top of the test file at compile time, before any `import` runs, so the module is already swapped out when your code imports it. That only works when `vi.mock` is written at the top level of the file. Inside `beforeEach`, the mock would only register after the module had been imported, so it couldn't affect it. Recent Vitest versions warn about `vi.mock` calls that aren't at the top level, and a stricter version turns that into an error, which is probably what you're seeing. I haven't checked the exact behaviour in your installed vitest 5.0.3, and the project's lessons file doesn't mention it. To fix it, use one of these: - **Mock once, reset per test:** put `vi.mock('./mod')` at the top level. Then in `beforeEach`, set up what each test needs with `vi.mocked(fn).mockReturnValue(...)` and clear it with `vi.resetAllMocks()`. - **Mock at runtime:** use `vi.doMock('./mod', factory)`, which isn't moved to the top. Then load the module with `await import('./mod')` after that call, and call `vi.resetModules()` between tests.