Claude Opus 5.5

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.

Answering cost $0.08.

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.

The judge's log

Session log

What the agent wrote, the tools it called, and what they returned, from docs/bench/2026-10-11-done3/runs/B-project-sync/vitest-5-0-0-16-b.jsonl. Thinking and the session's settings are left out. The raw log

  1. 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.