jestjs/jest · error · TypeError

Cannot replace the `${String(propertyKey)}` property because

Error message

Cannot replace the `${String(propertyKey)}` property because it is a function. Use `jest.spyOn(object, '${String(propertyKey)}')` instead.

What it means

Thrown by jest.replaceProperty (as a TypeError) when descriptor.value is a function. replaceProperty is meant for value properties; functions must be spied on with spyOn so call tracking and mockImplementation work. The message directs you to the correct API.

Source

Thrown at packages/jest-mock/src/index.ts:1510

          propertyKey,
        )}\` property because it has a getter. Use \`jest.spyOn(object, '${String(
          propertyKey,
        )}', 'get').mockReturnValue(value)\` instead.`,
      );
    }

    if (descriptor.set !== undefined) {
      throw new Error(
        `Cannot replace the \`${String(
          propertyKey,
        )}\` property because it has a setter. Use \`jest.spyOn(object, '${String(
          propertyKey,
        )}', 'set').mockReturnValue(value)\` instead.`,
      );
    }

    if (typeof descriptor.value === 'function') {
      throw new TypeError(
        `Cannot replace the \`${String(
          propertyKey,
        )}\` property because it is a function. Use \`jest.spyOn(object, '${String(
          propertyKey,
        )}')\` instead.`,
      );
    }

    const existingRestore = this._findReplacedProperty(object, propertyKey);

    if (existingRestore) {
      return existingRestore.replaced.replaceValue(value);
    }

    const isPropertyOwner = Object.prototype.hasOwnProperty.call(
      object,
      propertyKey,
    );

View on GitHub (pinned to 8e6d128e4a)

Solutions

  1. Use jest.spyOn(obj,'method').mockImplementation(newFn) for function properties.
  2. Reserve jest.replaceProperty for non-function values (numbers, strings, objects).
  3. Confirm with typeof obj.method === 'function' before choosing the API.

Example fix

// before
jest.replaceProperty(svc, 'fetch', mockFn); // fetch is a function
// after
jest.spyOn(svc, 'fetch').mockImplementation(mockFn);
Defensive patterns

Strategy: type-guard

Validate before calling

const d = Object.getOwnPropertyDescriptor(obj, propertyKey);
if (d && typeof d.value === 'function') {
  jest.spyOn(obj, propertyKey).mockImplementation(value as any);
} else {
  jest.replaceProperty(obj, propertyKey, value);
}

Type guard

const isFunctionValue = (o: object, k: PropertyKey): boolean => {
  const d = Object.getOwnPropertyDescriptor(o, k);
  return !!d && typeof d.value === 'function';
};

Prevention

When it happens

Trigger: jest.replaceProperty(obj,'method',newFn) where obj.method is a function.

Common situations: Confusing replaceProperty with spyOn; an API where a value became a method; auto-binded method properties.

Related errors


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