如何模拟作为参数传入的回调函数调用?含Jest场景疑问
模拟回调函数调用的实现方案(含Jest和非Jest两种方式)
我来帮你搞定这个问题——不管你用不用Jest,都能实现在外部灵活调用传入的回调函数,核心思路就是把回调先“存”到外部可访问的地方,之后想什么时候调用就什么时候调用。
方法一:用Jest实现(适合测试场景)
你当前的写法是在mockImplementation里直接调用了handler,但如果想在这个作用域外调用,只需要把handler存到一个外部变量里就行:
type YesOrNoHandler = (yesOrNo: boolean) => void; type CheckValue = (val: string, handler: YesOrNoHandler) => void; // 定义一个外部变量来存储回调函数 let storedHandler: YesOrNoHandler | undefined; const check = jest.fn().mockImplementation((_, handler) => { // 把传入的handler赋值给外部变量 storedHandler = handler; }); // 先触发一次check,让storedHandler拿到实际的回调 check('test input', (result) => { console.log('回调执行结果:', result); }); // 现在在任何地方都能调用这个回调了 if (storedHandler) { storedHandler(true); // 控制台会输出"回调执行结果: true" storedHandler(false); // 也可以传入false测试不同分支 }
这种方式特别适合测试异步逻辑,比如你需要在测试的某个阶段手动触发回调,验证后续的业务逻辑是否正确。
方法二:不使用Jest的通用方案
如果不用Jest,我们可以自己模拟这个逻辑,同样是把回调存到外部变量:
type YesOrNoHandler = (yesOrNo: boolean) => void; type CheckValue = (val: string, handler: YesOrNoHandler) => void; let storedHandler: YesOrNoHandler | undefined; // 自己实现一个模拟函数,保存传入的回调 const check: CheckValue = (val, handler) => { storedHandler = handler; // 如果需要保留原函数的业务逻辑,也可以在这里调用原函数 }; // 使用示例 check('user input', (isValid) => { if (isValid) { console.log('值有效'); } else { console.log('值无效'); } }); // 外部调用回调 storedHandler?.(true); // 输出"值有效" storedHandler?.(false); // 输出"值无效"
如果需要追踪函数的调用次数、传入参数等信息,还可以给模拟函数加统计逻辑:
const checkMock = { // 记录所有调用的参数 callHistory: [] as [string, YesOrNoHandler][], // 存储最新的回调 latestHandler: undefined as YesOrNoHandler | undefined, // 模拟函数本体 execute: function(val: string, handler: YesOrNoHandler) { this.callHistory.push([val, handler]); this.latestHandler = handler; } }; // 使用 checkMock.execute('test', (res) => console.log(res)); checkMock.latestHandler?.(true); // 输出true console.log(`check被调用了${checkMock.callHistory.length}次`); // 输出"check被调用了1次"
总结
不管用不用Jest,核心逻辑都是将传入的回调函数保存到一个外部可访问的变量中,之后就能在任意时机调用它了。Jest只是提供了更便捷的mock工具链,本质和我们自己写的模拟逻辑是一致的。
内容的提问来源于stack exchange,提问作者klefevre
相关产品推荐
相关产品推荐

