使用 vitest 做单元测试 - rxliuli blog
source link: https://blog.rxliuli.com/p/a9f8e0634b3f476687a2e844470fba44/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
使用 vitest 做单元测试
2.7k 字
23 分钟
本文最后更新于:2023年2月22日 晚上
vitest 是一个新的单元测试工具,它很快,默认支持 esm,兼容 jest api,可以被视为更好的 jest。在默认情况下,它支持以下正在使用的功能
- 支持 esm
- 兼容 jest api
- 支持 vite 的功能
- 支持多框架 react/vue
vitest 内部依赖 vite,但不需要安装 vite。
npm i -D vitest
好吧,实际上 vitest 是真正的零配置,支持 ts/esm/tsx,但如果你想要更多的功能,确实可以创建 vitest.config.ts 文件或者直接在 vite.config.ts 中添加配置。
基本上,它与 jest 类似,在要测试文件的同级目录创建一个 __tests__
文件夹,然后在其中创建一个文件,文件名以 .test.ts 结尾,文件内容如下
import { expect, it } from 'vitest'
it('hello', () => {
expect(1 + 2).eq(3)
})
然后运行 pnpm vitest hello.test.ts
就可以以监视模式运行单元测试了
如果有多个测试时可以使用 describe
分组
import { describe, expect, it } from 'vitest'
describe('math', () => {
it('add', () => {
expect(1 + 2).eq(3)
})
it('less', () => {
expect(1 - 2).eq(-1)
})
})
describe('string', () => {
it('hello', () => {
const hello = (name: string) => `hello ${name}`
expect(hello('world')).eq('hello world')
})
})
也可以使用 -t 参数指定要执行的测试,例如
pnpm vitest hello.test.ts -t 'add'
也可以使用 it.only/descrive.only
来指定要执行的测试
另外一些 beforeEach/afterEach 等钩子函数也是支持的
例如默认创建一个测试目录
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const tempPath = path.resolve(__dirname, '.temp', path.basename(__filename))
beforeEach(async () => {
await rm(tempPath, { recursive: true, force: true })
await mkdir(tempPath, { recursive: true })
})
afterEach(async () => {
await rm(tempPath, { recursive: true, force: true })
})
vitest 默认内嵌 chaijs 作为断言库,并且兼容了 jest 的断言 api。
最有趣的是,它支持某些断言很简洁,例如断言一些常见的值
expect(true).true
expect(false).false
expect(undefined).undefined
expect(null).null
或者对比值
expect(1).eq(1)
expect({ name: 'world' }).deep.eq({ name: 'world' }) // 深度对比
web api polyfill
通常在 web 项目中测试时也会包含一些 dom api,例如 localStorage/indexedDB 等。
happy-dom
dom 相关的 api mock 可以通过 happy-dom
来实现,它是一个简单的 dom 实现,可以在 node 中运行,虽然 api 比 jsdom 少一些,但速度要更快。
{
"test": {
"environment": "happy-dom"
}
}
使用 localStorage
expect(localStorage.getItem('test')).null
localStorage.setItem('test', 'test')
expect(localStorage.getItem('test')).eq('test')
localStorage.removeItem('test')
fetch
nodejs@18 支持了 fetch 请求,不再需要 polyfill。
indexedDB
遗憾的是 hyppy-dom 没有实现 indexedDB,所以我们需要使用 fake-indexeddb
做 polyfill。
这个不需要做什么配置,只需要在测试文件中引入即可
import 'fake-indexeddb/auto'
import { openDB } from 'idb'
it('indexeddb', async () => {
const db = await openDB<{
books: {
title: string
author: string
isbn: string
}
}>('test', 1, {
upgrade(db) {
db.createObjectStore('books', {
autoIncrement: true,
keyPath: 'isbn',
})
},
})
expect(await db.getAll('books')).empty
await db.add('books', {
title: 'Quarry Memories',
author: 'Fred',
isbn: 123456,
})
await db.add('books', {
title: 'Water Buffaloes',
author: 'Fred',
isbn: 234567,
})
expect(await db.getAll('books')).length(2)
})
- vitest 有一个 vscode 插件,但目前尚未支持 monorepo,所以建议不要使用
- vitest 基于 vite,
__dirname/__filename
等变量在测试中可用,但实际上在 nodejs esm 中不可用 - vitest 与 node:test 的 api 有重叠,尤其是 it/describe,要留意不要错误引用
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK