JavaScript测试疑难:如何测试返回未决议Promise的函数?
如何测试返回未决议Promise的JavaScript函数
这个问题挺常见的——毕竟未决议的Promise本身就是设计成不触发then/catch的,不过咱们可以从测试逻辑或者微小的函数调整入手,既满足业务要求,又能完成测试。下面给你几个可行的方案:
方案1:验证Promise的存在性与pending状态
如果你的测试核心需求只是确认函数确实返回了一个Promise,并且没有意外触发决议,那这个方案最直接:
test('函数返回未决议的Promise', () => { const result = yourFunction(); // 第一步:确认返回值是Promise实例 expect(result).toBeInstanceOf(Promise); // 第二步:验证短时间内Promise保持pending状态 return new Promise((resolve) => { setTimeout(() => { // 如果走到这里,说明在100ms内Promise没有被resolve/reject,测试通过 resolve(); }, 100); }); });
这里的超时时间可以根据你的业务逻辑调整,只要能覆盖“函数不会意外决议”的场景就行。
方案2:模拟Promise构造函数,验证内部逻辑
如果需要确认函数内部是否正确处理了Promise的resolve/reject引用(只是没触发),可以用测试框架的mock能力来劫持Promise:
以Jest为例:
test('函数正确创建了未决议的Promise', () => { let resolveMock, rejectMock; // 模拟全局Promise构造函数 jest.spyOn(global, 'Promise').mockImplementation((executor) => { resolveMock = jest.fn(); rejectMock = jest.fn(); // 把mock的resolve/reject传给函数的executor executor(resolveMock, rejectMock); // 返回一个真正的未决议Promise return new Promise(() => {}); }); const result = yourFunction(); // 验证Promise确实被调用了 expect(Promise).toHaveBeenCalled(); // 这里可以根据你的业务逻辑,验证resolve/reject是否被正确保存(比如存到了外部变量) // 示例:expect(yourModule.exposedResolve).toBe(resolveMock); // 测试结束后恢复原Promise,避免影响其他测试 global.Promise.mockRestore(); });
这个方案适合需要深入验证函数内部逻辑,但又不想修改业务代码的场景。
方案3:给函数加测试专用开关(微小调整,不影响生产)
如果允许对业务函数做极其微小的改动(完全不影响生产行为),可以添加一个测试模式开关,手动触发决议来完整测试then/catch流程:
修改业务函数:
function yourFunction(options = {}) { let resolveRef, rejectRef; const promise = new Promise((resolve, reject) => { resolveRef = resolve; rejectRef = reject; // 原业务逻辑:不主动触发resolve/reject }); // 仅在测试环境或手动开启测试模式时暴露决议方法 if (process.env.NODE_ENV === 'test' || options.testMode) { promise._testResolve = resolveRef; promise._testReject = rejectRef; } return promise; }
测试时的代码:
test('函数的业务逻辑能正确触发then回调', async () => { const promise = yourFunction({ testMode: true }); // 手动触发resolve,模拟业务逻辑完成后的行为 promise._testResolve('预期的返回值'); // 现在可以正常await并验证结果 const result = await promise; expect(result).toBe('预期的返回值'); });
这个方案的好处是能完整测试Promise决议后的流程,同时生产环境下完全看不到这些测试专用的方法。
内容的提问来源于stack exchange,提问作者Julian Mendez
相关产品推荐
相关产品推荐

