Vitest 测试框架基本用法
一、Vitest 的安装及配置
1、安装
yarn add -D vitest
在 package.json 中添加:
package.json
{
"scripts": {
"test": "vitest"
}
}
2、基本用法
- sum.js
- sum.test.js
sum.js
function sum(a, b) {
return a + b;
}
export default sum
使用 expect 和 toBe 来测试两值是否一致:
sum.test.js
import { expect, it } from 'vitest'
import sum from './sum'
it('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
})
运行 yarn test
,终端输出:
Vitest 的默认匹配规则与 jest 相似,可通过根目录下的 vite.config.ts 的 include 自定义匹配:
vite.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
include: // ...
},
})
二、Vitest 常用的匹配器
1、相等
toBe() 用来测试两个值是否相等:
expect(2 + 2).toBe(4);
toEqual() 会递归检查数组或对象的每个字段,用来测试两个对象是否相等:
const data = {one: 1};
data['two'] = 2;
expect(data).toEqual({one: 1, two: 2});
2、数字
数字大小的比较可以通过以下匹配器来进行匹配:
test('two plus two', () => {
const value = 2 + 2;
expect(value).toBeGreaterThan(3);
expect(value).toBeGreaterThanOrEqual(3.5);
expect(value).toBeLessThan(5);
expect(value).toBeLessThanOrEqual(4.5);
// toBe and toEqual are equivalent for numbers
expect(value).toBe(4);
expect(value).toEqual(4);
});
对于浮点数的比较,需使用 toBeCloseTo 而非 toBe,否则会导致舍入误差:
test('两个浮点数字相加', () => {
const value = 0.1 + 0.2;
// expect(value).toBe(0.3); 这句会报错,因为浮点数有舍入误差
expect(value).toBeCloseTo(0.3); // 这句可以运行
});
3、取反
not 可以表达相反匹配:
expect(a + b).not.toBe(0);
4、真值
可以使用以下真值判断 undefined, null, false 等:
- toBeNull 只匹配 null
- toBeUndefined 只匹配 undefined
- toBeDefined 与 toBeUndefined 相反
- toBeTruthy 匹配任何 if 语句为真
- toBeFalsy 匹配任何 if 语句为假
test('null', () => {
const n = null;
expect(n).toBeNull();
expect(n).toBeDefined();
expect(n).not.toBeUndefined();
expect(n).not.toBeTruthy();
expect(n).toBeFalsy();
});
test('zero', () => {
const z = 0;
expect(z).not.toBeNull();
expect(z).toBeDefined();
expect(z).not.toBeUndefined();
expect(z).not.toBeTruthy();
expect(z).toBeFalsy();
});
5、包含
可以通过 toContain 来检查一个数组或可迭代对象是否包含某个特定项:
const shoppingList = [
'diapers',
'kleenex',
'trash bags',
'paper towels',
'milk',
];
test('shoppingList 数组中包含 milk', () => {
expect(shoppingList).toContain('milk');
expect(new Set(shoppingList)).toContain('milk');
});
三、模拟对象
vitest 的 vi 提供了一系列的模拟对象:
1、模拟日期
import { it, vi } from 'vitest'
beforeEach(() => {
// 告诉 vitest 使用模拟时间
vi.useFakeTimers()
})
it('set system time', () => {
// 在工作时间内设置时间
const date = new Date(2000, 1, 1, 13)
vi.setSystemTime(date)
// ...
})
afterEach(() => {
// 每次测试运行后恢复日期
vi.useRealTimers()
})
2、模拟函数
import { mount } from '@vue/test-utils';
import { it, expect, vi } from 'vitest';
import Button from '@/src/button/index';
it('onClick', () => {
const clickFn = vi.fn();
const wrapper = mount({
render() {
return <Button onClick={clickFn} />;
},
});
wrapper.findComponent(Button).trigger('click');
expect(clickFn).toHaveBeenCalled();
});
四、测试钩子
1、重复运行
beforeEach 可以在文件中每个测试用例开始前做一些预执行工作,afterEach 可以在每个测试用例结束后进行一些清理工作:
beforeEach(() => {
initializeCityDatabase();
});
afterEach(() => {
clearCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
2、一次性运行
beforeAll 和 afterAll 可以在文件中所有测试用例开始前和结束后一次性执行,而不用每个测试用例都执行一遍,从而影响性能:
beforeAll(() => {
return initializeCityDatabase();
});
afterAll(() => {
return clearCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
3、作用域
可以通过 describe 块来将测试用例分组:
beforeAll(() => console.log('1 - beforeAll'));
afterAll(() => console.log('1 - afterAll'));
beforeEach(() => console.log('1 - beforeEach'));
afterEach(() => console.log('1 - afterEach'));
test('', () => console.log('1 - test'));
describe('Scoped / Nested block', () => {
beforeAll(() => console.log('2 - beforeAll'));
afterAll(() => console.log('2 - afterAll'));
beforeEach(() => console.log('2 - beforeEach'));
afterEach(() => console.log('2 - afterEach'));
test('', () => console.log('2 - test'));
});
输出: