{"record":{"id":"9a3e5883f6eb6788","repo":"denoland/deno","slug":"beforeeach-requires-a-function","errorCode":null,"errorMessage":"beforeEach() requires a function","messagePattern":"beforeEach\\(\\) requires a function","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/testing.ts","lineNumber":1620,"sourceCode":"  }\n\n  before(fn, _options) {\n    if (typeof fn !== \"function\") {\n      throw new TypeError(\"before() requires a function\");\n    }\n    ArrayPrototypePush(this.#beforeHooks, fn);\n  }\n\n  after(fn, _options) {\n    if (typeof fn !== \"function\") {\n      throw new TypeError(\"after() requires a function\");\n    }\n    ArrayPrototypePush(this.#afterHooks, fn);\n  }\n\n  beforeEach(fn, _options) {\n    if (typeof fn !== \"function\") {\n      throw new TypeError(\"beforeEach() requires a function\");\n    }\n    ArrayPrototypePush(this.#beforeEachHooks, fn);\n  }\n\n  afterEach(fn, _options) {\n    if (typeof fn !== \"function\") {\n      throw new TypeError(\"afterEach() requires a function\");\n    }\n    ArrayPrototypePush(this.#afterEachHooks, fn);\n  }\n\n  // Runs this context's `before()` hooks a single time, before its first\n  // subtest. Idempotent so it is safe to call from every subtest's step.\n  async _runBeforeHooksOnce() {\n    if (this.#beforeHooksRun) return;\n    this.#beforeHooksRun = true;\n    // deno-lint-ignore no-this-alias\n    const ctx = this;","sourceCodeStart":1602,"sourceCodeEnd":1638,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/testing.ts#L1602-L1638","documentation":"t.beforeEach(fn) on the node:test context registers a hook run before each of this test's subtests. The implementation pushes fn onto an internal array and requires typeof fn === 'function'; otherwise it throws TypeError 'beforeEach() requires a function'.","triggerScenarios":"t.beforeEach() with no argument; t.beforeEach(seedRow(...)) passing a query result; passing a describe-style name string first.","commonSituations":"Seed/reset helpers invoked instead of referenced; hook helpers imported as default objects and passed wholesale (t.beforeEach(hooks) where hooks.seed was meant).","solutions":["Pass the function reference: t.beforeEach(seedRow)","Reference the specific method when importing an object of helpers: t.beforeEach(hooks.seed)","Check dynamically sourced hooks with typeof before registering"],"exampleFix":"// before\nt.beforeEach(resetDb());\n\n// after\nt.beforeEach(resetDb);","handlingStrategy":"type-guard","validationCode":"if (typeof seed !== 'function') {\n  throw new TypeError(`t.beforeEach: expected function, got ${typeof seed}`);\n}\nt.beforeEach(seed);","typeGuard":"const isHookFn = (fn) => typeof fn === 'function';\n\nif (isHookFn(seed)) {\n  t.beforeEach(seed);\n}","tryCatchPattern":null,"preventionTips":["Reference helper objects' methods explicitly: t.beforeEach(hooks.seed)","Do not pass a name string or describe block as the hook","Validate dynamic hook sources with typeof before registering"],"tags":["node-test","hooks","api-misuse"],"backgroundTag":"test-hook-requires-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"}