如何在Jasmine中mock函数?调用saveBooking未触发mock的checkStatus报错求助
问题根因
mock失效的核心原因有两点:
Booking.js中saveBooking调用的是模块内部私有作用域下的checkStatus函数,而你用spyOn打桩的是模块导出对象module.exports上挂载的checkStatus属性,两者不是同一个引用,因此实际调用没有命中mock。- 原有
saveBooking没有返回内部的Promise链,await Booking.saveBooking(req)实际是等待了一个undefined,会在checkStatus异步执行完成前就触发断言,也会导致测试报错。
解决方案1:调整业务代码调用逻辑(成本最低)
修改Booking.js,让内部调用指向导出对象的方法,同时返回Promise链:
// Booking.js 修改后代码 const checkStatus = (id) => { // some code here return new Promise((resolve, reject)=>{ resolve(value); }); } const saveBooking =(req) => { // 1. 改为调用exports上的checkStatus,和mock的对象保持一致 // 2. 加return把Promise暴露出去,await才能正常等待异步执行完成 return module.exports.checkStatus(req.id).then(()=>{ //save booking here .. }).catch((error)=>{ throw new Error(); }); } module.exports = {saveBooking, checkStatus}
解决方案2:优化测试用例代码
你测试用例中使用的$q是AngularJS的异步工具,没有必要额外引入,直接用Jasmine内置的Promise mock方法即可:
// booking.Spec.js 修改后代码 const Booking = require('Booking'); describe('Booking',()=>{ const req = { id: 2133, customer_name: 'John Smith', contact_number: '888-8888', contact_email: 'cam888@example.com' }; it('Should check the status', async ()=>{ // 简化mock逻辑,直接返回resolve的Promise spyOn(Booking, "checkStatus").and.resolveTo(true); await Booking.saveBooking(req); expect(Booking.checkStatus).toHaveBeenCalledWith(req.id); // 增加参数校验逻辑更严谨 }); });
可选方案:不修改业务代码mock私有函数
如果不想调整业务代码的调用逻辑,可以引入rewire模块直接修改模块内部的私有checkStatus变量,也能实现mock效果。
内容的提问来源于stack exchange,提问作者cam
相关产品推荐
相关产品推荐

