单元测试

vitestopen in new window

jestopen in new window

Jest

安装

pnpm add --save-dev jest

第一个测试

// main.js
function add(a, b) {
  return a + b
}

function sub(a, b) {
  return a - b
}

module.exports = {
  add,
  sub
}

// main.test.js
const { add, sub } = require('./main')

test('5+5=10', () => {
  expect(add(5, 5)).toBe(10)
})

test('5-5=0', () => {
  expect(sub(5, 5)).toBe(0)
})

配置测试命令

// package.json
"scripts": {
  "test": "jest"
}

初始化Jest配置

pnpm jest init

默认配置会生成终端测试覆盖率报告,和covrage文件夹里面的前端网页报告

Jest 的匹配器

  • toBe()匹配器,是在工作中最常用的一种匹配器,简单的理解它就是相等。这个相当是等同于===的,也就是我们常说的严格相等
// pass
test('toBe匹配器', () => {
  expect('这是一个toBe').toBe('这是一个toBe')
})

// FAIL
test('toBe匹配器完全相等', () => {
  const obj = { number: 999 }
  expect(obj).toBe({ number: 999 })
})
  • toEqual()匹配器,内容相等,就可以通过测试
// pass
test('toBe匹配器完全相等', () => {
  const obj = { number: 999 }
  expect(obj).toEqual({ number: 999 })
})

当你不严格匹配但要求值相等时时就可以使用toEqual()匹配器

  • toBeNul() 匹配器只匹配null值,需要注意的是不匹配undefined的值
test('toBeNul 只匹配null', () => {
  const a = null
  expect(a).toBeNull()
})

// 等价于
test('toBeNul 只匹配null', () => {
  const a = null
  expect(a).toBe(null)
})
  • toBeUndifined()匹配
test('toBeUndifined', () => {
  const a = undefined
  expect(a).toBeUndefined()
})
  • toBeDefined() 只要定义过就可以通过
test('toBeDefine', () => {
  const a = 1
  expect(a).toBeDefined()
})
  • toBeTruthy() 只要不是false0""nullundefinedNaN,就可以通过
// pass
test('toBeTruthy', () => {
  const a = 1
  expect(a).toBeTruthy()
})

// fail
test('toBeTruthy', () => {
  const a = 0
  expect(a).toBeTruthy()
})
  • toBeFalsy()toBeTruthy()相对
test('toBeFalsy', () => {
  const a = 0
  expect(a).toBeFalsy()
})
  • toBeGreaterThan(number | bigint)大于什么数值,只要大于传入的数值,就可以通过测试
test('toBeGreaterThan匹配器', () => {
  const a = 10
  expect(a).toBeGreaterThan(9.9);
});

test('toBeGreaterThan匹配器', () => {
  const a = 10n
  expect(a).toBeGreaterThan(9n);
});
  • toBeGreaterThanOrEqual(number | bigint)大于等于什么数值,只要大于等于传入的数值,就可以通过测试
test(`toBeGreaterThanOrEqual()`, () => {
  const a = 10
  expect(a).toBeGreaterThanOrEqual(10);
})
  • toBeLessThan(number | bigint) 小于什么数值,只要小于传入的数值,就可以通过测试
test(`toBeLessThan()`, () => {
  const a = 10
  expect(a).toBeLessThan(100);
})
  • toBeLessThanOrEqual(number | bigint) 小于等于什么数值,只要小于等于传入的数值,就可以通过测试
test(`toBeLessThanOrEqual()`, () => {
  const a = 10
  expect(a).toBeLessThanOrEqual(10);
})
  • toBeCloseTo(number, numDigits?) 这个是可以自动消除JavaScript浮点精度错误的匹配器
// fails
test('toEqual匹配器', () => {
  const one = 0.1
  const two = 0.2
  // expect(one + two).toEqual(0.3)
})

// pass
test('toBeCloseTo', () => {
  const one = 0.1
  const two = 0.2
  expect(one + two).toBeCloseTo(0.3, 5);
})
  • toMatch(regexp | string) 字符串包含匹配器
test('toMatch()', () => {
  const a = 'qwertyuiop'
  expect(a).toMatch('iop');
})
  • toContain(item) 字符串数组包含匹配器
test('toContain()', () => {
  const a = ['a', 'b', 'c', 'd']
  expect(a).toContain('c');
})

test('toContain()', () => {
  const a = ['a', 'b', 'c', 'd', 'a']
  const mySet = new Set(a)
  expect(mySet).toContain('c');
})
  • toThrow(error?) 专门对异常进行处理的匹配器,可以检测一个方法会不会抛出异常,可以对这个匹配器中加一些字符串,意思就是抛出的异常必须和字符串相对应,如果字符串不匹配,也没办法通过异常测试
test('toThrow', () => {
  const a = () => {
    throw new Error('error')
  }
  expect(() => {
    a()
  }).toThrow('error');
})
  • .not 取反
test('not', () => {
  expect(1).not.toBe(2)
})

引入ES6支持和import

Jest 默认支持的是 CommonJS 规范,使用babel 转换成 CommonJS 规范

pnpm add --save-dev babel-jest @babel/core @babel/preset-env

可以在工程的根目录下创建一个babel.config.js文件用于配置与你当前Node版本兼容的Babel

module.exports = {
  presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
};

异步代码的测试方法-1回调函数式

// fetchData.js
import axios from 'axios'

export const getPost = (fn) => {
  axios.get('https://jsonplaceholder.typicode.com/posts/1').then(res => {
    fn(res.data)
  })
}

// fetchData.test.jsimport { getPost } from "./fetchData";

test('异步代码测试', (done) => {
  getPost(data => {
    expect(data.id).toEqual(1)
    done()
  })
});

在测试代码中使用done表示保证我们的回调已经完成了

异步代码的测试方法-2直接返回promise

export const getPost2 = () => {
  return axios.get('https://jsonplaceholder.typicode.com/posts/2')
}

test('异步代码测试 返回promise', () => {
  return getPost2().then(res => {
    expect(res.data.id).toEqual(2);
  })
});

异步代码的测试方法-3不存在接口的测试方法

test('测试接口错误', () => {
  expect.assertions(1) // 必须执行一次
  return getError().catch(e => {
    expect(e.toString().indexOf('404' > -1)).toBeTruthy();
  })
});

expect.assertions(1)必须执行一次expect否则catch只有异常才会执行

异步代码的测试方法-4async...await

test('异步代码测试 async await', async () => {
  const res = await getPost2();
  expect(res.data.id).toEqual(2);
});

Jest中的四个钩子函数

  • beforeAll 在所有测试用例之前进行执行。

  • afterAll 是在完成所有测试用例之后才执行的函数。

  • beforeEach 钩子函数,是在每个测试用例前都会执行一次的钩子函数

  • afterEach 在每次测试用例完成测试之后执行一次的钩子函数

贡献者: huxiguo