javascript测试框架如何编写单元测试?【教程】

13次阅读

用 Jest 写第一个 test 函数需安装 jest、命名文件为 .test.js 或 .spec.js,用 test() 包裹断言,expect() 后接匹配器如 toBe()。

javascript测试框架如何编写单元测试?【教程】

怎么用 Jest 写第一个 test 函数

Jest 是当前最主流的 javaScript 单元测试框架,开箱即用,不用配 Babel 或打包工具就能跑 es6+ 语法。写测试前先确保项目里装了 Jest:npm install --save-dev jest,并在 package.jsonscripts 里加一行:"test": "jest"

测试文件名必须以 .test.js.spec.js 结尾(比如 math.test.js),Jest 才会自动识别。每个测试用 test()it() 包裹,第一个参数是描述性字符串,第二个是回调函数

test('add(1, 2) returns 3', () => {   expect(add(1, 2)).toBe(3); });

注意:expect() 后面必须跟匹配器(如 toBe()toEqual()),不能直接写 add(1, 2) === 3——那样失败时没错误,也看不到期望值与实际值的差异。

describe()beforeEach() 怎么组织多个测试用例

当一个模块有多个函数或同一函数有多种输入场景时,用 describe() 分组能让测试结构清晰,报错时也更容易定位到哪一组出问题。它不改变执行逻辑,只是语义分组:

立即学习Java免费学习笔记(深入)”;

describe('User validation', () => {   test('rejects empty name', () => { /* ... */ });   test('accepts valid email', () => { /* ... */ }); });

如果多个测试共用某个对象或状态(比如初始化一个 new UserService() 实例),用 beforeEach() 比在每个 test() 里重复创建更安全、更易维护:

  • 避免测试间状态污染(比如某个测试修改了全局变量或实例属性)
  • 所有测试从干净状态开始,结果可重现
  • 如果初始化耗时,还可以考虑 beforeAll(),但得小心副作用

异步代码怎么测?async/awaitpromise 的写法区别

Jest 默认等待测试函数同步执行完就结束,遇到异步操作会直接跳过断言,导致“测试通过但其实没跑”。必须显式告诉 Jest:等我这个异步动作完成再判结果。

三种合法写法(任选其一):

  • 返回 Promise:在 test() 回调里 return fetch('/api').then(...)
  • async/await:函数声明为 async,里面用 await 等待,Jest 自动识别
  • 传入 done 回调:在函数参数里加 done,手动调用 done() 表示完成(容易忘调,不推荐)

错误示范:test('fetches user', () => { fetch('/user').then(res => expect(res.ok).toBe(true)); }); —— 这个 expect 永远不会被 Jest 等待,测试必然“假通过”。

为什么 mock 不生效?常见陷阱在哪

Mock 的核心是“替换真实依赖”,但 Jest 的 jest.mock() 是**自动 hoist 到文件顶部**的,这意味着你不能在 requireimport 之后才调用它——那样模块已经加载完了,mock 失效。

正确做法只有两种:

  • jest.mock('axios') 放在 import 语句之后、任何测试代码之前(Jest 会自动提升,但写在上面更直观)
  • 用工厂函数形式动态控制返回值:jest.mock('axios', () => ({ get: jest.fn().mockResolvedValue({ data: 'ok' }) }));

另一个高频坑:mock 模块里的默认导出(export default)时,要 mock 整个模块,而不是只 mock 某个方法名;ESM 下还要注意 __esModule: true 兼容性,有时得用 jest.requireactual() 保留部分真实行为。

真实项目里,边界越清晰(比如 API 调用全收口在 service 层)、mock 越简单;把 fetch 直接塞进组件里,后续就只能靠 msw 拦网络请求,成本高得多。

text=ZqhQzanResources