From 638d19096af967f265614582952c48c0da3dd137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=93=E5=8F=91=E5=8F=97=E9=95=BF=E7=94=9F?= Date: Sun, 21 Jul 2019 21:49:21 +0800 Subject: [PATCH] =?UTF-8?q?Jest=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- images/JavaScript/运行jest.png | Bin 0 -> 36243 bytes source/_posts/JavaScript/Jest单元测试.md | 212 +++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 images/JavaScript/运行jest.png create mode 100644 source/_posts/JavaScript/Jest单元测试.md diff --git a/images/JavaScript/运行jest.png b/images/JavaScript/运行jest.png new file mode 100644 index 0000000000000000000000000000000000000000..312ded2175ac22478e26162876096e2dd224f9d5 GIT binary patch literal 36243 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 literal 0 HcmV?d00001 diff --git a/source/_posts/JavaScript/Jest单元测试.md b/source/_posts/JavaScript/Jest单元测试.md new file mode 100644 index 0000000..d0d8154 --- /dev/null +++ b/source/_posts/JavaScript/Jest单元测试.md @@ -0,0 +1,212 @@ +--- +title: Jest单元测试 +date: 2019-07-21 00:41:10 +tags: + - JavaScript + - 单元测试 +categories: + - JavaScript +--- + +`Jest`是由Facebook开源的一个测试框架,它集成了断言库、mock、快照测试、覆盖率报告等功能。它非常适合用来测试React代码,但不仅仅如此,所有的js代码都可以使用Jest进行单元测试 + + +### 安装 +直接执行`yarn add jest --dev`或者`npm install jest --save-dev`来安装到nodejs项目 +会附带同时安装jest-cli这个命令行工具 +可以在命令行直接执行jest命令运行单元测试代码 + +所以可以在package.json当中添加 +```json +"scripts": { + "test": "jest" +} +``` +运行测试的时候直接执行`yarn test`或者`npm run test`即可 +当然也可以用npx, 也就是`npx jest` + +### Hello World +如果我们编写了一个函数, 要测试它的执行是否能达到预期结果 +```javascript +// main.js +function sum(a, b) { + return a + b +} +module.exports = { sum } +``` +jest会递归查找项目当中所有的名为`*.test.js`以及`*.spec.js` +通常是把单元测试文件与源码文件同名(不是必须) +```javascript +// main.test.js +const { sum } = require('../main') + +test('Adding 2 + 3 equals 5', () => { + expect(sum(2, 3)).toBe(5) +}) +``` +> 这里虽然使用了jest提供的一些函数,但是测试代码当中并不需要进行引入 +jest会帮我们引入这些 +test也可以用it,完全一样,没有差别 + +![运行jest](/images/JavaScript/运行jest.png) + +test是运行一个测试用例,第一个参数是对该测试的描述,会在执行结果中打印出来 +在此代码中,`expect(sum(2, 3))`返回一个“期望”对象,`.toBe(2)`是匹配器。匹配器将期望的结果(实际值)与自己的参数(期望值)进行比较 +当Jest运行时,它会跟踪所有失败的匹配器,并打印出错误信息 + +常用的匹配器 ++ `toBe` 使用 Object.is 判断是否严格相等。 ++ `toEqual` 递归检查对象或数组的每个字段。 ++ `toBeNull` 只匹配 null。 ++ `toBeUndefined` 只匹配 undefined。 ++ `toBeDefined` 只匹配非 undefined。 ++ `toBeTruthy` 只匹配真。 ++ `toBeFalsy` 只匹配假。 ++ `toBeGreaterThan` 实际值大于期望。 ++ `toBeGreaterThanOrEqual` 实际值大于或等于期望值 ++ `toBeLessThan` 实际值小于期望值。 ++ `toBeLessThanOrEqual` 实际值小于或等于期望值。 ++ `toBeCloseTo` 比较浮点数的值,避免误差。 ++ `toMatch` 正则匹配。 ++ `toContain` 判断数组中是否包含指定项。 ++ `toHaveProperty(keyPath, value)` 判断对象中是否包含指定属性。 ++ `toThrow` 判断是否抛出指定的异常。 ++ `toBeInstanceOf` 判断对象是否是某个类的实例,底层使用 instanceof。 + +所有的匹配器均可以使用`.not`取反 +比如 +```javascript +test('Adding 2 + 3 not equals 10', () => { + expect(sum(2, 3)).not.toBe(10) +}) +``` + +### Promise对象 +当然实际情况一般没有这么简单,很多需要异步操作的函数返回的都是Promise对象 +```javascript +const func1 = async () => { + return Promise.resolve('success') +} +const func2 = async () => { + return Promise.reject('failed') +} +``` +测试代码 +```javascript +test('the func1 should resolve success', () => { + return expect(func1()).resolves.toBe('success') +}) +test('the func1 should reject failed', () => { + return expect(func2()).rejects.toBe('failed') +}) +``` +也可以使用await +```javascript +test('the func1 should resolve success', async () => { + const result = await func1() + expect(result).toBe('success') +}) + +test('the func2 should reject failed', async () => { + try { + await func2() + } catch (err) { + expect(err).toBe('failed') + } +}) +``` + +### 抛出错误的匹配 +可以使用`toThrow`或者`toThrowError`(并没发现这两者的不同)来校验函数抛出了指定的错误 +```javascript +const func3 = () => { + throw new Error('this error') +} + +test('the func3 throw Error', () =>{ + function func3Wrapper() { + func3() + } + expect(func3Wrapper).toThrowError() + expect(func3Wrapper).toThrowError('this error') + expect(func3Wrapper).toThrowError(/^this/) + expect(func3Wrapper).toThrowError(new Error('this error')); +}) +``` +需要注意的是,抛出异常的方法**必须放在包装函数**内 +也就是给expect传递一个函数,而不是目标函数的执行结果 +否则无法捕获异常,也就无法判断抛出的异常是否匹配 +参数是可选的,可以是 ++ 字符串 - 与Error对象的message完全一致 ++ 正则对象 - 与Error对象的message可以匹配 ++ Error对象 - 与抛出的Error对象一致 + +### 钩子函数 +Jest提供了四个测试用例的钩子:**beforeAll、afterAll、beforeEach、afterEach**。 +`beforeAll` 和 `afterAll` 会在所有测试用例之前和所有测试用例之后执行一次。 +`beforeEach` 和 `afterEach` 会在每个测试用例之前和之后执行。 + +如果测试用例较多,可以用`describe`将测试用例分组 +在describe块中的钩子函数只作用于块内的测试用例: +```javascript +beforeAll(() => console.log('out - beforeAll')) // 1 +afterAll(() => console.log('out - afterAll')) // 12 +beforeEach(() => console.log('out - beforeEach')) // 2,6 +afterEach(() => console.log('out - afterEach')) // 4,10 +test('', () => console.log('out - test')) // 3 +describe('Scoped / Nested block', () => { + beforeAll(() => console.log('in - beforeAll')) // 5 + afterAll(() => console.log('in - afterAll')) // 11 + beforeEach(() => console.log('in - beforeEach')) // 7 + afterEach(() => console.log('in - afterEach')) // 9 + test('', () => console.log('in - test')) // 8 +}) +``` +外部的beforeAll会先于所有分组内的执行 +外部的afterAll会在所有分组执行完毕后执行 + +外部的beforeEach会在所有测试用例执行前执行,并且先于分组内的beforeEach +外部的afterEach会在所有测试用例执行后执行,晚于分组内的beforeEach + +这些钩子函数通常用于测试用例执行前后一些资源的初始化和销毁操作 + +### Mock函数 +调用`jest.fn()`即可获得一个mock函数。 Mock函数有一个特殊的mock属性,保存着函数的调用信息 +比如我们需要测试多组数据,并提供入参和返回值的期望 +```javascript +function sum(a, b) { + return a + b +} + +test('test forEach function', () => { + const sumCallback = jest.fn(sum) + const testData = [ + [[1,2], 3], + [[2,3], 5], + [[3,5], 8], + [[101,102], 203] + ] + testData.forEach(item => { + sumCallback.apply(null, item[0]) + }) + expect(sumCallback.mock.calls.length).toBe(testData.length) + testData.forEach((item,index) => { + // 通过calls属性可以拿到每次调用的入参(数组形式) + expect(sumCallback.mock.calls[index]).toEqual(item[0]) + // 通过results属性可以拿到每次调用的返回值 + expect(sumCallback.mock.results[index].value).toBe(item[1]) + }) +}) +``` + +### Jest配置 +Jest可以在package.json当中通过`jest`属性来指定配置项 +或者默认引入`jest.config.js`(如果存在) +也可以通过`--config`参数指定配置文件,该配置文件可以是json格式或者js格式 +js格式需要使用`module.exports`来暴露出配置内容对象,供jest获取 + +执行`jest --init`可以初始化一个配置文件,包含多数配置项的默认值 + +其他常用参数 ++ `--watch` 以监视模式启动 ++ `--coverage` 生成覆盖率报告 \ No newline at end of file