Sinon是否兼容Vitest?单元测试加载Sinon模块失败问题咨询
问题结论
Sinon 完全兼容 Vitest,你遇到的 [vite-node] Failed to load sinon 报错是依赖加载模式适配问题,不是兼容性问题,按以下步骤修复即可。
修复步骤
- 升级 Sinon 到适配 ESM 的版本
Sinon 14.0 之前的版本对 ESM 模块规范的适配不完善,vite-node 以 ESM 模式加载依赖时会触发解析失败,先执行命令升级到最新稳定版:
npm i sinon@latest @types/sinon@latest -D
- 配置 Vitest 兼容模式(升级后仍报错时操作)
如果升级完依赖还是报加载错误,在 Vitest 配置里把 sinon 加入内联依赖列表,让 vite-node 以兼容 CommonJS 的模式处理该模块。打开vite.config.ts,添加如下配置:
import { defineConfig } from 'vitest/config' export default defineConfig({ test: { // 你原有其他测试配置保持不变 deps: { inline: ['sinon'] } } })
- 修正测试代码的逻辑错误
解决加载问题后,你现有测试代码还有三处逻辑问题会导致用例执行失败:getName是异步 action,调用后没有等待 Promise 状态落定就直接断言,会拿不到最终的 state 值- 没有在测试结束后恢复 stub 过的 axios 方法,会污染其他测试用例的上下文
- stub 的返回值结构和 store 里的取值逻辑不匹配:你的 store 代码里先取了
response.data,之后又对返回结果取了一次.data,原 stub 返回的结构少了一层嵌套
修正后的测试代码如下:
import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { useCounterStore } from '../counter'; import { setActivePinia, createPinia } from 'pinia'; import axios from 'axios'; import sinon from 'sinon'; describe('useCounterStore', () => { beforeEach(() => { setActivePinia(createPinia()); }); afterEach(() => { // 恢复所有stub,避免跨用例污染 sinon.restore(); }); it.skip('Counter Store - increment()', () => { const counter = useCounterStore(); expect(counter.counter).toBe(0); counter.increment(); expect(counter.counter).toBe(1); }); it('getName - axios success', async () => { const counter = useCounterStore(); // 匹配store里的两层.data取值逻辑 sinon.stub(axios, 'get').resolves({ data: { data: 'abc' } }); // 等待异步action执行完成 await counter.getName(); expect(counter.name).toEqual('abc'); }); });
补充说明
Vitest 内置的 vi 对象提供了和 Sinon 语法几乎完全一致的 spy、stub、mock 能力,不需要额外安装依赖,如果后续团队愿意切换,可以无缝替换 Sinon,不需要重新学习 API。
内容的提问来源于stack exchange,提问作者Art Tsai
相关产品推荐
相关产品推荐

