Skip to content

vitest 实战

在看了文章在任何一个项目中快速引入 vitest 后,我们来看看 vitest 的实战应用。

配置环境

vitest 默认的环境为 node,所以没有 document、window 这些全局对象。如果像让 vitest 的环境变为浏览器,可以使用 jsdom。

js
import { defineConfig } from 'vitest/config';
import path from 'path';

export default defineConfig({
    test: {
        environment: 'jsdom'
    }
});

配置路径别名

js
import { defineConfig } from 'vitest/config';
import path from 'path';

export default defineConfig({
    test: {
    // ...
        include: ['test/*.{test,spec}.?(c|m)[jt]s?(x)'],
        alias: [ 
            { 
                find: '@', 
                replacement: path.resolve(__dirname, 'src') 
            } 
        ], 
        environment: 'jsdom'
    }
});

配置断言 api 不用导入

为了可以让全局 API 支持 Typescript,需要将 vitest/globals 添加到 tsconfig.json 中的 types 选项中

json
// tsconfig.json
{
  "compilerOptions": {
    "types": ["vitest/globals"]
  }
}

断言

某个对象或数组拥有某个结构

会递归比较。

ts
import { expect, test } from 'vitest'

const stockBill = {
  type: 'apples',
  count: 13,
}

const stockMary = {
  type: 'apples',
  count: 13,
}

test('stocks have the same properties', () => {
  expect(stockBill).toEqual(stockMary)
})

test('stocks are not the same', () => {
  expect(stockBill).not.toBe(stockMary)
})

断言某个值不为 undefined

js
expect('').toBeDefined()
expect({}).toBeDefined()

测试异步代码

可以使用 async、await 测试异步代码

js
test('the data is peanut butter', async () => {
  const data = await fetchData();
  expect(data).toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
  expect.assertions(1);
  try {
    await fetchData();
  } catch (e) {
    expect(e).toMatch('error');
  }
})

断定字符串包含某个字符序列

ts
  test('toContain', () => {
    const str =  'ABCD'
    expect(str).toContain('AB')
  })

断定数组中包含某个元素

断定一个数组中包含元素字符串 1。

ts
  test('toContain', () => {
    const arr1 =  ['1',2,'c']
    // ok
    expect(arr1).toContain('1')
  })

断定数组中包含一个与给定值相同结构的元素

ts
  test('toContainEqual', () => {
    const arr = [1, 2, 3, {a:1,b:2}]
    // 错误
    // expect(arr).toContainEqual({a:1})
    // 成功
    expect(arr).toContainEqual({a:1,b:2})
  })

测试覆盖率

Vitest 通过 v8 支持原生代码覆盖率,通过 istanbul 支持检测代码覆盖率。

在 vites.config.ts 中配置覆盖率提供者:

js
  coverage: {
    provider: 'v8' // 'istanbul'。默认 v8。
  },

然后下载依赖。如果不下载,在跑覆盖率的时候也会提醒你下载。

shell
pnpm i -D @vitest/coverage-v8

然后配置一个脚本,跑覆盖率:

json
"coverage": "vitest run --coverage"

执行脚本后:

其中它们每个字段代表的含义如下

  • %stmts 是语句覆盖率(statement coverage):是不是每个语句都执行了?
  • %Branch 分支覆盖率(branch coverage):是不是每个 if 代码块都执行了?
  • %Funcs 函数覆盖率(function coverage):是不是每个函数都调用了?
  • %Lines 行覆盖率(line coverage):是不是每一行都执行了?

断定某个对象有哪些键值对

ts
  expect(getHashAndParam(windowLocationUrl)).toEqual({
    vConsole: '1',
    key: 'DSFLSDFSDFSCDSDF',
    xcxFlag: 'mallhome'
  })

Released under the MIT License.