{"record":{"id":"c631c14c34c28ddd","repo":"jestjs/jest","slug":"spyon-no-method-name-supplied-usage-spyon-ob","errorCode":null,"errorMessage":"<spyOn> : No method name supplied\nUsage: spyOn(<object>, <methodName>)","messagePattern":"<spyOn> : No method name supplied\nUsage: spyOn\\(<object>, <methodName>\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/jest-jasmine2/src/jasmine/spyRegistry.ts","lineNumber":96,"sourceCode":"    this.allowRespy = function (allow) {\n      this.respy = allow;\n    };\n\n    this.spyOn = (obj, methodName, accessType) => {\n      if (accessType) {\n        return this._spyOnProperty(obj, methodName, accessType);\n      }\n\n      if (obj === void 0) {\n        throw new Error(\n          getErrorMsg(\n            `could not find an object to spy upon for ${methodName}()`,\n          ),\n        );\n      }\n\n      if (methodName === void 0) {\n        throw new Error(getErrorMsg('No method name supplied'));\n      }\n\n      if (obj[methodName] === void 0) {\n        throw new Error(getErrorMsg(`${methodName}() method does not exist`));\n      }\n\n      if (obj[methodName] && isSpy(obj[methodName])) {\n        if (this.respy) {\n          return obj[methodName];\n        } else {\n          throw new Error(\n            getErrorMsg(`${methodName} has already been spied upon`),\n          );\n        }\n      }\n\n      let descriptor;\n      try {","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/jestjs/jest/blob/8e6d128e4a278059ecddecaa97400b04c8ae5fd9/packages/jest-jasmine2/src/jasmine/spyRegistry.ts#L78-L114","documentation":"Thrown by SpyRegistry.spyOn when the methodName argument is undefined (spyRegistry.ts:96). The second argument names the method to replace; omitting it (or passing undefined) leaves the registry unable to look up the property to spy on.","triggerScenarios":"spyOn(obj) with only one argument, spyOn(obj, undefined), spyOn(obj, methodName) where methodName is computed from a variable that resolved to undefined, or destructuring that forgot to pull the name.","commonSituations":"Refactor renaming a method but forgetting the spy call; dynamically computing the method name from a config object whose key is missing; copy-paste from a template leaving the second slot empty; mocking with spread args that drop the name.","solutions":["Supply the literal method name: spyOn(obj, 'methodName').","If the name is dynamic, validate it first: if (!name) throw new Error('method name required'); spyOn(obj, name);.","Use TypeScript to type the second arg as keyof typeof obj so an undefined is rejected at compile time.","Double-check the spy call was not truncated by an auto-formatter that removed a line."],"exampleFix":"// before\nspyOn(obj);\n// after\nspyOn(obj, 'methodName');","handlingStrategy":"validation","validationCode":"if (methodName === undefined || methodName === null) {\n  throw new Error('spyOn: methodName argument is required');\n}\nspyOn(obj, methodName);","typeGuard":"const hasMethodName = <T extends object>(o: T, k: PropertyKey): k is keyof T =>\n  typeof k === 'string' && k in o;","tryCatchPattern":null,"preventionTips":["Always pass the literal method name string.","Type the second arg as keyof typeof obj.","Avoid computing the name from possibly-missing config keys."],"tags":["jest","spyon","mocking","undefined","api-misuse"],"backgroundTag":null,"analyzedSha":"8e6d128e4a278059ecddecaa97400b04c8ae5fd9","analyzedAt":"2026-08-10T18:11:27.960Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}