Commit f513ec7e7ca for nodejs

commit f513ec7e7cad019368f26528041e9684ab12fba6
Author: Guilherme Araújo <arauujogui@gmail.com>
Date:   Fri Oct 16 15:06:44 2026 -0300

    test_runner: add mockReturnValue and promise helpers

    Add mockReturnValue(), mockResolvedValue() and mockRejectedValue()
    to MockFunctionContext as shorthands for common mockImplementation()
    patterns.

    Signed-off-by: Guilherme Araújo <arauujogui@gmail.com>
    PR-URL: https://github.com/nodejs/node/pull/66631
    Reviewed-By: Chemi Atlow <chemi@atlow.co.il>

diff --git a/doc/api/test.md b/doc/api/test.md
index 4df041dbdfb..48d5b0c004c 100644
--- a/doc/api/test.md
+++ b/doc/api/test.md
@@ -2466,6 +2466,89 @@ test('changes a mock behavior once', (t) => {
 });
 ```

+### `ctx.mockRejectedValue(reason)`
+
+<!-- YAML
+added: REPLACEME
+-->
+
+* `reason` {any} The value the returned promise rejects with.
+
+Changes the mock's implementation to a function that returns a promise rejected
+with `reason`. This is shorthand for
+`ctx.mockImplementation(() => Promise.reject(reason))`.
+
+```js
+test('mocks a rejected value', async (t) => {
+  const fn = t.mock.fn();
+
+  fn.mock.mockRejectedValue(new Error('boom'));
+  await assert.rejects(fn(), { message: 'boom' });
+});
+```
+
+### `ctx.mockResolvedValue(value)`
+
+<!-- YAML
+added: REPLACEME
+-->
+
+* `value` {any} The value the returned promise resolves with.
+
+Changes the mock's implementation to a function that returns a promise resolved
+with `value`. This is shorthand for
+`ctx.mockImplementation(() => Promise.resolve(value))`.
+
+```js
+test('mocks a resolved value', async (t) => {
+  const fn = t.mock.fn();
+
+  fn.mock.mockResolvedValue(42);
+  assert.strictEqual(await fn(), 42);
+});
+```
+
+### `ctx.mockReturnValue(value)`
+
+<!-- YAML
+added: REPLACEME
+-->
+
+* `value` {any} The value returned by the mock.
+
+Changes the mock's implementation to a function that returns `value`. This is
+shorthand for `ctx.mockImplementation(() => value)`.
+
+```js
+test('mocks a return value', (t) => {
+  const fn = t.mock.fn();
+
+  fn.mock.mockReturnValue(42);
+  assert.strictEqual(fn(), 42);
+  assert.strictEqual(fn(), 42);
+});
+```
+
+### `ctx.mockThrownValue(value)`
+
+<!-- YAML
+added: REPLACEME
+-->
+
+* `value` {any} The value thrown by the mock.
+
+Changes the mock's implementation to a function that throws `value`. This is
+shorthand for `ctx.mockImplementation(() => { throw value; })`.
+
+```js
+test('mocks a thrown value', (t) => {
+  const fn = t.mock.fn();
+
+  fn.mock.mockThrownValue(new Error('boom'));
+  assert.throws(fn, { message: 'boom' });
+});
+```
+
 ### `ctx.resetCalls()`

 <!-- YAML
diff --git a/lib/internal/test_runner/mock/mock.js b/lib/internal/test_runner/mock/mock.js
index 996c8a7bcca..4861f31b5f2 100644
--- a/lib/internal/test_runner/mock/mock.js
+++ b/lib/internal/test_runner/mock/mock.js
@@ -15,6 +15,8 @@ const {
   ObjectKeys,
   ObjectSetPrototypeOf,
   ObjectValues,
+  PromiseReject,
+  PromiseResolve,
   Proxy,
   ReflectApply,
   ReflectConstruct,
@@ -143,6 +145,38 @@ class MockFunctionContext {
     this.#mocks.set(call, implementation);
   }

+  /**
+   * Sets a new implementation that always returns the given value.
+   * @param {any} value - The value to return.
+   */
+  mockReturnValue(value) {
+    this.#implementation = function() { return value; };
+  }
+
+  /**
+   * Sets a new implementation that returns a promise resolved with the given value.
+   * @param {any} value - The value to resolve with.
+   */
+  mockResolvedValue(value) {
+    this.#implementation = function() { return PromiseResolve(value); };
+  }
+
+  /**
+   * Sets a new implementation that returns a promise rejected with the given reason.
+   * @param {any} reason - The reason to reject with.
+   */
+  mockRejectedValue(reason) {
+    this.#implementation = function() { return PromiseReject(reason); };
+  }
+
+  /**
+   * Sets a new implementation that always throws the given value.
+   * @param {any} value - The value to throw.
+   */
+  mockThrownValue(value) {
+    this.#implementation = function() { throw value; };
+  }
+
   /**
    * Restores the original function that was mocked.
    */
diff --git a/test/parallel/test-runner-mocking.js b/test/parallel/test-runner-mocking.js
index 634eff93165..59a919579e7 100644
--- a/test/parallel/test-runner-mocking.js
+++ b/test/parallel/test-runner-mocking.js
@@ -892,6 +892,52 @@ test('mock implementation can be changed dynamically', (t) => {
   assert.strictEqual(fn.mock.callCount(), 12);
 });

+test('mockReturnValue() sets a fixed return value', (t) => {
+  const fn = t.mock.fn(common.mustNotCall());
+
+  fn.mock.mockReturnValue(42);
+  assert.strictEqual(fn(), 42);
+  assert.strictEqual(fn(1, 2), 42);
+  assert.strictEqual(fn.mock.callCount(), 2);
+  assert.strictEqual(fn.mock.calls[1].result, 42);
+});
+
+test('mockResolvedValue() returns a resolved promise', async (t) => {
+  const fn = t.mock.fn(common.mustNotCall());
+
+  fn.mock.mockResolvedValue(42);
+  const result = fn();
+  assert(result instanceof Promise);
+  assert.strictEqual(await result, 42);
+});
+
+test('mockRejectedValue() returns a rejected promise', async (t) => {
+  const fn = t.mock.fn(common.mustNotCall());
+  const error = new Error('boom');
+
+  fn.mock.mockRejectedValue(error);
+  await assert.rejects(fn(), error);
+});
+
+test('mockThrownValue() throws the given value', (t) => {
+  const fn = t.mock.fn(common.mustNotCall());
+  const error = new Error('boom');
+
+  fn.mock.mockThrownValue(error);
+  assert.throws(fn, error);
+  assert.strictEqual(fn.mock.callCount(), 1);
+  assert.strictEqual(fn.mock.calls[0].error, error);
+});
+
+test('mockImplementationOnce() takes precedence over mockReturnValue()', (t) => {
+  const fn = t.mock.fn();
+
+  fn.mock.mockReturnValue(1);
+  fn.mock.mockImplementationOnce(() => 2);
+  assert.strictEqual(fn(), 2);
+  assert.strictEqual(fn(), 1);
+});
+
 test('local mocks are auto restored after the test finishes', async (t) => {
   const obj = {
     foo() {},