{"record":{"id":"e4edd2f8de5b5876","repo":"oxc-project/oxc","slug":"suggest-using-jest-spyon-or-vi-spyon","errorCode":null,"errorMessage":"Suggest using `jest.spyOn()` or `vi.spyOn()`.","messagePattern":"Suggest using `jest\\.spyOn\\(\\)` or `vi\\.spyOn\\(\\)`\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/shared/jest_vitest/prefer_spy_on.rs","lineNumber":21,"sourceCode":"    ast::{\n        Argument, AssignmentExpression, CallExpression, Expression, MemberExpression,\n        SimpleAssignmentTarget,\n    },\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_semantic::AstNode;\nuse oxc_span::Span;\n\nuse crate::{\n    context::LintContext,\n    fixer::RuleFixer,\n    utils::{\n        KnownMemberExpressionProperty, PossibleJestNode, get_node_name, parse_general_jest_fn_call,\n    },\n};\n\nfn use_jest_spy_on(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Suggest using `jest.spyOn()` or `vi.spyOn()`.\").with_label(span)\n}\n\npub const DOCUMENTATION: &str = r\"### What it does\n\nWhen mocking a function by overwriting a property you have to manually restore\nthe original implementation when cleaning up. When using `jest.spyOn()` Jest\nkeeps track of changes, and they can be restored with `jest.restoreAllMocks()`,\n`mockFn.mockRestore()` or by setting `restoreMocks` to `true` in the Jest\nconfig.\n\nNote: The mock created by `jest.spyOn()` still behaves the same as the original\nfunction. The original function can be overwritten with\n`mockFn.mockImplementation()` or by some of the\n[other mock functions](https://jestjs.io/docs/en/mock-function-api).\n\n### Why is this bad?\n\nDirectly overwriting properties with mock functions can lead to cleanup issues","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/shared/jest_vitest/prefer_spy_on.rs#L3-L39","documentation":"This is the oxlint `prefer-spy-on` rule (jest/vitest plugin), with an autofix. Overwriting a property with `jest.fn()` (`Date.now = jest.fn()`) replaces the original and makes you responsible for restoring it — easy to forget, causing cross-test leakage. `jest.spyOn()`/`vi.spyOn()` records calls while keeping the original implementation and can be restored centrally via `jest.restoreAllMocks()`, `mockRestore()`, or the `restoreMocks` config. The fixer rewrites the assignment to the spyOn form, preserving any `mockImplementation` chain.","triggerScenarios":"An AssignmentExpression whose left side is a member expression (`obj.prop = ...` or computed `obj[key] = ...`) and whose right side is a `jest.fn()`/`vi.fn()` call — including member chains like `obj.prop = jest.fn().mockImplementation(() => 10)` — detected via `parse_general_jest_fn_call` with first member `fn`.","commonSituations":"Mocking global/static methods (`Date.now`, `Math.random`, `window.fetch`) by direct assignment; stubbing imported module methods on namespace objects; teams hitting flaky tests because a previous test's overwritten property leaked into later ones.","solutions":["Apply the autofix or rewrite manually: `Date.now = jest.fn(() => 10)` → `jest.spyOn(Date, 'now').mockImplementation(() => 10)`.","Enable `restoreMocks: true` in jest config (or call `jest.restoreAllMocks()` in afterEach) so spies are restored automatically.","For computed properties keep the computed form: `jest.spyOn(obj, key)`."],"exampleFix":"// before\nDate.now = jest.fn(() => 10);\n\n// after\njest.spyOn(Date, 'now').mockImplementation(() => 10);","handlingStrategy":"validation","validationCode":"// .oxlintrc.json\n{ \"rules\": { \"jest/prefer-spy-on\": \"error\" } }\n\nnpx oxlint --fix tests/  # autofix rewrites assignments to spyOn\n\n// jest.config.js\nmodule.exports = { restoreMocks: true };","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never assign jest.fn()/vi.fn() to an object property; spyOn keeps the original restorable.","Enable restoreMocks: true (or afterEach(jest.restoreAllMocks)) so spies cannot leak across tests.","Run `oxlint --fix` on legacy suites to bulk-convert direct-property mock assignments."],"tags":["jest","vitest","oxlint","testing","mocks","spies","autofix","static-analysis"],"backgroundTag":"mock-spy-on","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}