jestjs/jest · error · Error

<spyOn> : could not find an object to spy upon for ${methodN

Error message

<spyOn> : could not find an object to spy upon for ${methodName}()
Usage: spyOn(<object>, <methodName>)

What it means

Thrown by SpyRegistry.spyOn when the target object argument is undefined (spyRegistry.ts:88). spyOn requires a real object instance whose method will be replaced; a missing import, a not-yet-initialised module, or a destructuring that yields undefined means there is nothing to attach the spy to.

Source

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

    accessType: keyof PropertyDescriptor,
  ) => Spy;

  constructor({
    currentSpies = () => [],
  }: {
    currentSpies?: () => Array<Spy>;
  } = {}) {
    this.allowRespy = function (allow) {
      this.respy = allow;
    };

    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 {

View on GitHub (pinned to 8e6d128e4a)

Solutions

  1. Verify the import path and shape: log `typeof obj` immediately before spyOn; ensure it is an object.
  2. For ESM interop, use `import * as Namespace from 'mod'` and spy on Namespace.member, or call jest.unstable_mockModule correctly.
  3. For prototype spies, confirm the class is fully defined: spyOn(MyClass.prototype, 'method').
  4. If the object is optional, guard: if (obj) spyOn(obj, 'method');.

Example fix

// before
import {fs} from './fs';
spyOn(fs, 'readFile'); // fs is undefined
// after
import * as fs from 'node:fs';
spyOn(fs, 'readFile');
Defensive patterns

Strategy: validation

Validate before calling

if (obj === undefined || obj === null) {
  throw new Error('spyOn: target object is undefined; check the import');
}
spyOn(obj, 'method');

Type guard

const isSpyTarget = (v: unknown): v is Record<string, any> =>
  v !== null && v !== undefined && typeof v === 'object';

Try / catch

try {
  spyOn(obj, 'method');
} catch (e) {
  if (e.message.includes('could not find an object')) {
    // log the import source, then rethrow or skip
  }
  throw e;
}

Prevention

When it happens

Trigger: spyOn(undefined, 'fetch'), spyOn(fs, 'readFile') where fs was never imported, spyOn(SomeClass.prototype, 'method') before the class is defined, or spyOn(obj, 'method') where obj is conditionally undefined.

Common situations: ESM/CJS interop where the default import is wrapped and the named member is undefined; importing a side-effect-only module that exports nothing; spying on a prototype of a class defined in another file with circular import timing; mock factory returning undefined.

Related errors


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