{"record":{"id":"74c4965b75517a7b","repo":"denoland/deno","slug":"cannot-mock-property-string-methodname-becau-74c496","errorCode":null,"errorMessage":"Cannot mock property '${String(methodName)}' because it is not a function","messagePattern":"Cannot mock property '(.+?)' because it is not a function","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/testing.ts","lineNumber":2516,"sourceCode":"    throw new TypeError(\n      `Cannot mock property '${String(methodName)}' because it does not exist`,\n    );\n  }\n\n  const isGetter = options?.getter ?? false;\n  const isSetter = options?.setter ?? false;\n\n  let original;\n  if (isGetter) {\n    original = descriptor.get;\n  } else if (isSetter) {\n    original = descriptor.set;\n  } else {\n    original = descriptor.value;\n  }\n\n  if (typeof original !== \"function\") {\n    throw new TypeError(\n      `Cannot mock property '${\n        String(methodName)\n      }' because it is not a function`,\n    );\n  }\n\n  const restore = () => {\n    ObjectDefineProperty(object, methodName, {\n      __proto__: null,\n      ...descriptor,\n    });\n  };\n\n  const impl = implementation === undefined ? original : implementation;\n  const ctx = new MockFunctionContext(impl, restore, options?.times);\n  ArrayPrototypePush(activeMocks, ctx);\n\n  const mockFn = createMockFunction(original, impl, ctx);","sourceCodeStart":2498,"sourceCodeEnd":2534,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/testing.ts#L2498-L2534","documentation":"After finding the descriptor, mock.method() selects descriptor.value (or descriptor.get/descriptor.set when the getter/setter options are set) and requires it to be a function. A data property holding a non-function value, or a getter/setter flag that does not match the descriptor's kind (descriptor.get is undefined on a data property), throws this TypeError.","triggerScenarios":"mock.method(user, 'id') where id is a number; mock.method(obj, 'value', impl, { getter: true }) when 'value' is a plain data property; { setter: true } against a getter-only accessor.","commonSituations":"Confusing value mocks with method mocks; assuming an API is an accessor when the implementation uses a plain field; version changes replacing a getter with a data field.","solutions":["For non-function values use mock.property(obj, 'id', 42) instead of mock.method","Match the flag to the descriptor kind: { getter: true } only for accessors with a get, { setter: true } only with a set","Inspect first: const d = Object.getOwnPropertyDescriptor(obj, 'id'); check typeof d.value / typeof d.get","If both getter and setter exist, pass the flag matching the half you replace"],"exampleFix":"// before\nmock.method(user, 'id', () => 42); // 'id' is a number, not a function\n\n// after\nmock.property(user, 'id', 42);","handlingStrategy":"validation","validationCode":"const d = Object.getOwnPropertyDescriptor(obj, name);\nconst target = options?.getter ? d?.get : options?.setter ? d?.set : d?.value;\nif (typeof target !== 'function') {\n  // pick the right tool: property mock for values, method mock for functions\n}","typeGuard":"function isMockableFn(o: object, k: PropertyKey): boolean {\n  const v = (o as Record<PropertyKey, unknown>)[k];\n  return typeof v === 'function';\n}","tryCatchPattern":"try { mock.method(obj, name, impl, opts); } catch (e) { if (e instanceof TypeError && /not a function/.test(e.message)) { mock.property(obj, name, fallbackValue); } else throw e; }","preventionTips":["Check typeof obj[name] === 'function' before mock.method without getter/setter flags","Match the getter/setter flag to the descriptor kind found on the object","Log the descriptor when a mock fails to set up"],"tags":["node-test","mock","mock-method","type-check"],"backgroundTag":"not-a-function","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}