From 5f010c65d8abb8bb4aa6b26ff76ee3fe61563c34 Mon Sep 17 00:00:00 2001 From: fuyou Date: Thu, 31 Jul 2025 12:45:38 +0800 Subject: [PATCH] fix(mock): add support for rejected values in JSMockFunction (#21489) --- src/bun.js/bindings/JSMockFunction.cpp | 10 ++++++++-- test/js/bun/test/mock-fn.test.js | 5 +++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index a852d532fe..92f4e15cbd 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -148,6 +148,7 @@ public: Call, ReturnValue, ReturnThis, + RejectedValue, }; static JSMockImplementation* create(JSC::JSGlobalObject* globalObject, JSC::Structure* structure, Kind kind, JSC::JSValue heldValue, bool isOnce) @@ -962,6 +963,11 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje setReturnValue(createMockResult(vm, globalObject, "return"_s, thisValue)); return JSValue::encode(thisValue); } + case JSMockImplementation::Kind::RejectedValue: { + JSValue rejectedPromise = JSC::JSPromise::rejectedPromise(globalObject, impl->underlyingValue.get()); + setReturnValue(createMockResult(vm, globalObject, "return"_s, rejectedPromise)); + return JSValue::encode(rejectedPromise); + } default: { RELEASE_ASSERT_NOT_REACHED(); } @@ -1235,7 +1241,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRejectedValue, (JSC::JSGlobalObject * auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); - pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, JSC::JSPromise::rejectedPromise(globalObject, callframe->argument(0))); + pushImpl(thisObject, globalObject, JSMockImplementation::Kind::RejectedValue, callframe->argument(0)); RELEASE_AND_RETURN(scope, JSValue::encode(thisObject)); } @@ -1248,7 +1254,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRejectedValueOnce, (JSC::JSGlobalObje auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); - pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, JSC::JSPromise::rejectedPromise(globalObject, callframe->argument(0))); + pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::RejectedValue, callframe->argument(0)); RELEASE_AND_RETURN(scope, JSValue::encode(thisObject)); } diff --git a/test/js/bun/test/mock-fn.test.js b/test/js/bun/test/mock-fn.test.js index 4f813f7ffa..6f67cefa1f 100644 --- a/test/js/bun/test/mock-fn.test.js +++ b/test/js/bun/test/mock-fn.test.js @@ -599,6 +599,11 @@ describe("mock()", () => { expect(await expectRejects(fn())).toBe(44); expect(await expectRejects(fn())).toBe(42); }); + test("mockRejectedValue doesn't throw when never called", () => { + const fn = jest.fn().mockRejectedValue(new Error("Test error")); + expect(fn).toBeDefined(); + expect(typeof fn).toBe("function"); + }); test("withImplementation (sync)", () => { const fn = jest.fn(() => "1"); expect(fn()).toBe("1");