jestjs/jest · error · Error

<spyOn> : ${methodName}() method does not exist Usage: spyOn

Error message

<spyOn> : ${methodName}() method does not exist
Usage: spyOn(<object>, <methodName>)

What it means

Thrown by SpyRegistry.spyOn when obj[methodName] is undefined (spyRegistry.ts:100). The method must exist on the object as an own or inherited property; spying on a non-existent method would silently create a fake that has no underlying behaviour, so Jest refuses.

Source

Thrown at packages/jest-jasmine2/src/jasmine/spyRegistry.ts:100

    this.spyOn = (obj, methodName, accessType) => {
      if (accessType) {
        return this._spyOnProperty(obj, methodName, accessType);
      }

      if (obj === void 0) {
        throw new Error(
          getErrorMsg(
            `could not find an object to spy upon for ${methodName}()`,
          ),
        );
      }

      if (methodName === void 0) {
        throw new Error(getErrorMsg('No method name supplied'));
      }

      if (obj[methodName] === void 0) {
        throw new Error(getErrorMsg(`${methodName}() method does not exist`));
      }

      if (obj[methodName] && isSpy(obj[methodName])) {
        if (this.respy) {
          return obj[methodName];
        } else {
          throw new Error(
            getErrorMsg(`${methodName} has already been spied upon`),
          );
        }
      }

      let descriptor;
      try {
        descriptor = Object.getOwnPropertyDescriptor(obj, methodName);
      } catch {
        // IE 8 doesn't support `definePropery` on non-DOM nodes
      }

View on GitHub (pinned to 8e6d128e4a)

Solutions

  1. Confirm the method exists: console.log(typeof obj.methodName) before spyOn.
  2. For function-style exports, refactor to a member (obj.method = fn) or use jest.spyOn on a wrapper module.
  3. Spy on the correct receiver: spyOn(MyClass.prototype, 'method') for instance methods shared across instances.
  4. After a dependency upgrade, grep the changelog for the renamed method and update the spy.

Example fix

// before
spyOn(logger, 'logInfo'); // method renamed in v3
// after
spyOn(logger, 'info');
Defensive patterns

Strategy: validation

Validate before calling

if (typeof obj[methodName] !== 'function') {
  throw new Error(`spyOn: ${String(methodName)} is not a function on the target`);
}
spyOn(obj, methodName);

Type guard

const hasMethod = <T extends object>(o: T, k: string): k is keyof T & string =>
  typeof (o as any)[k] === 'function';

Prevention

When it happens

Trigger: spyOn(obj, 'nonExistent'), spy on a method that was renamed in the library, spy on a prototype method using the instance (or vice versa), or spy on a method exported as a plain function rather than a member.

Common situations: Upgrading a dependency that renamed or removed a method; spying on a function-style export (`export const fn = () => {}`) which is not a member of any object; spying on a class method via the instance when the method is actually on a parent prototype not in the chain; typos in method names.

Related errors


AI-assisted analysis of jestjs/jest@8e6d128e4a (2026-08-10). Data as JSON: /api/errors/b3da6046082b5d7c. Report an issue: GitHub.