{"id":"0d031b7d39e6dda1","repo":"jestjs/jest","slug":"spies-must-be-created-in-a-before-function-or-a-sp","errorCode":null,"errorMessage":"Spies must be created in a before function or a spec","messagePattern":"Spies must be created in a before function or a spec","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/jest-jasmine2/src/jasmine/Env.ts","lineNumber":364,"sourceCode":"        }\n      };\n\n      this.addReporter = function (reporterToAdd) {\n        reporter.addReporter(reporterToAdd);\n      };\n\n      this.provideFallbackReporter = function (reporterToAdd) {\n        reporter.provideFallbackReporter(reporterToAdd);\n      };\n\n      this.clearReporters = function () {\n        reporter.clearReporters();\n      };\n\n      const spyRegistry = new j$.SpyRegistry({\n        currentSpies() {\n          if (!currentRunnable()) {\n            throw new Error(\n              'Spies must be created in a before function or a spec',\n            );\n          }\n          return runnableResources[currentRunnable().id].spies;\n        },\n      });\n\n      this.allowRespy = function (allow) {\n        spyRegistry.allowRespy(allow);\n      };\n\n      this.spyOn = function (...args) {\n        return spyRegistry.spyOn.apply(spyRegistry, args);\n      };\n\n      const suiteFactory = function (description: Circus.TestNameLike) {\n        const suite = new j$.Suite({\n          id: getNextSuiteId(),","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/jest-jasmine2/src/jasmine/Env.ts#L346-L382","documentation":"Jasmine's spy registry stores created spies against the currently-executing runnable (a spec or a before/after). The currentSpies() provider in Env.ts:361-369 throws when currentRunnable() is null — meaning spyOn was called at the top level of the file, outside any describe/beforeEach/it. Spies must be tied to a runnable so they can be torn down after it completes.","triggerScenarios":"Calling `jest.spyOn(...)` (or jasmine spyOn) directly in the module body of a test file or in a describe block's synchronous body (not inside a before* or it). currentRunnable() returns null because no spec or before/after is executing at that moment, so the provider at Env.ts:362 throws.","commonSituations":"Refactoring a test and moving a spyOn out of beforeEach to the top level; calling spyOn during module evaluation (e.g. in a helper imported for side effects); forgetting to wrap setup in beforeEach; spy creation triggered by an import statement.","solutions":["Move the spyOn call inside beforeEach/beforeAll or inside the it() body where a runnable is active.","If the spy is needed across setup, define it inside beforeAll and reference the returned spy handle in tests.","Avoid module-level side effects that call spyOn during import."],"exampleFix":"// before — spy created at top level (no runnable)\nconst spy = jest.spyOn(math, 'add');\ndescribe('math', () => { it('adds', () => { ... }); });\n\n// after — spy created inside a runnable\ndescribe('math', () => {\n  let spy;\n  beforeEach(() => { spy = jest.spyOn(math, 'add'); });\n  afterEach(() => { spy.mockRestore(); });\n  it('adds', () => { ... });\n});","handlingStrategy":"validation","validationCode":"// Static check: ensure spyOn/jest.spyOn calls live inside a runnable body.\n// Simple heuristic: the call's nearest enclosing function is it/test/before*/after*.\n// (Enforce via an ESLint custom rule or a pre-test scan.)\nfunction spyNotInRunnable(source: string): boolean {\n  // returns true if a jest.spyOn/spyOn call appears at describe-body top level\n  return /describe\\([^)]*\\)\\s*=>\\s*{[^}]*spyOn/.test(source);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always create spies inside beforeEach/beforeAll/it, never at module or describe top level.","Restore spies in afterEach to avoid leakage that encourages re-spying at the wrong scope.","Avoid module side effects that call spyOn during import."],"tags":["jasmine2","spy","spyon","test-structure","runnable"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}