在Vue Vitest中如何Mock Bugsnag Notify方法并验证其调用?
在Vitest中Mock Bugsnag.notify的正确姿势
先理清你的两个错误根源
TypeError: [Function] is not a spy or a call to a spy!—— 你要断言的Bugsnag.notify不是Vitest的间谍函数(spy),必须先把它转换成spy才能用toHaveBeenCalled()这类断言方法。Error: [vitest] No "default" export is defined on the "@bugsnag/js" mock—— Mock模块时没有匹配Bugsnag的真实导出结构(比如它是默认导出还是具名导出),需要在vi.mock里返回对应结构的Mock对象。
方法1:完全Mock整个@bugsnag/js模块
如果你的代码只用到notify方法,不需要Bugsnag其他真实功能,直接Mock整个模块即可:
步骤1:编写Mock逻辑
在测试文件顶部添加vi.mock,创建包含spy版notify的Mock对象:
// 多数情况下Bugsnag是默认导出,按这个写 vi.mock('@bugsnag/js', () => ({ default: { notify: vi.fn() // 把notify转成Vitest间谍函数 } })); // 如果你项目里用的是具名导入(import { Bugsnag } from '@bugsnag/js'),改成: // vi.mock('@bugsnag/js', () => ({ // Bugsnag: { // notify: vi.fn() // } // }));
步骤2:导入并编写测试用例
导入Bugsnag和被测函数,调用后断言:
import Bugsnag from '@bugsnag/js'; import { test, expect } from 'vitest'; import { triggerFailureFlow } from './your-module'; // 你的被测函数 test('失败流程中正确调用Bugsnag.notify', () => { // 触发失败流程 triggerFailureFlow(); // 断言notify被调用 expect(Bugsnag.notify).toHaveBeenCalled(); // 进一步断言传入的错误是否符合预期 expect(Bugsnag.notify).toHaveBeenCalledWith(expect.any(Error)); // 或者匹配具体错误信息 expect(Bugsnag.notify).toHaveBeenCalledWith(expect.objectContaining({ message: '预期的错误提示文本' })); });
方法2:部分Mock(保留Bugsnag其他真实功能)
如果你的代码还用到Bugsnag的其他方法,不想完全Mock,用vi.importActual导入真实模块后,单独替换notify为spy:
vi.mock('@bugsnag/js', async () => { // 导入真实的Bugsnag模块 const actual = await vi.importActual('@bugsnag/js'); return { ...actual, // 保留所有真实导出 default: { ...actual.default, // 保留默认导出的其他方法 notify: vi.fn() // 只把notify替换成spy } }; }); // 测试用例和方法1一致 test('失败流程中调用Bugsnag.notify', () => { triggerFailureFlow(); expect(Bugsnag.notify).toHaveBeenCalledWith(expect.any(Error)); });
特殊情况:Bugsnag是实例化使用的
如果你的代码里是先初始化Bugsnag客户端再调用notify,需要Mock客户端实例的notify:
vi.mock('@bugsnag/js', () => ({ default: { start: vi.fn().mockReturnValue({ notify: vi.fn() }) } })); // 测试时获取实例的notify来断言 test('实例化调用时的notify断言', () => { const bugsnagClient = Bugsnag.start({ apiKey: 'fake-key' }); triggerFailureFlow(); expect(bugsnagClient.notify).toHaveBeenCalled(); });
内容的提问来源于stack exchange,提问作者Taimoor Changaiz
相关产品推荐
相关产品推荐

