做为一个前端工程师,我是很想去谢单元测试的,由于天天的需求不少,还要去编写测试代码,感受时间都不够用了。javascript
不过最近开发了一个比较复杂的项目,让我感受一旦项目大了、复杂了,并且仍是多人维护一个应用,编写测试代码,css
仍是颇有必要的。毕竟这样作完以后,后边的维护会轻松不少。前端
测试代码的最小单元,一个函数就是一个单元java
主要用到的测试工具是 jest 和 enzymenode
jest 是 facebook 发布的一个开源的,基于 jasmine 框架的 javascript 单元测试工具它提供了不少有效的功能,react
包含了内置的测试环境的 DOM API 来操做 Dom、断言库、mock 等功能,而且 jest 是 react 的官网上面推荐jquery
的工具。webpack
enzyme 是 Airbnb 开源的 react 测试类库,提供了一套简洁强大的 api ,能够经过 jq 的风格进行 dom 处理,git
还能够引用一些其余的 dom 操做库。github
react 项目是基于 webpack + babel 来进行构建的。
首先须要添加一些 jest + enzyme 的 npm 包
yarn add jest enzyme babel-jest regenerator-runtime react-test-renderer
enzyme 须要安装对应的 react 的 adapter 版本
yarn add enzyme-adapter-react-16
一、package.json
"scripts": { "test": "jest --colors --coverage" },
添加颜色和现实覆盖率
.babelrc 文件
"env": { // 单元测试下配置 "test": { "presets": [ "react", "react-optimize", [ "env", { "modules": "commonjs", // 主要是添加这个 "debug": true, "useBuiltIns": false, "targets": { "browsers": "defaults" } } ], "stage-0" ] } }
由于测试环境的在 babel 中的配置 dev 为 test。
因此这里须要特殊配置,modules 的形式是 commonjs
添加jest配置文件jest.config
module.exports = { roots: ['<rootDir>/__test__/', '<rootDir>/src/'], // 测试的目录 modulePaths: ['<rootDir>'], coveragePathIgnorePatterns: ['/node_modules/', '/tests/setup.js'], //忽略统计覆盖率的文件 // bail: true, // testRegex: '', // 后缀名称 // testPathIgnorePatterns: 'est', // 忽略路径 // moduleNameMapper: { // 与测试无关的资源文件赞成mock 掉,这样在import 的时候就不会真的引入这些文件 // '^import?': '<rootDir>/build/jestImportMock.js', // '\\.(css|less|gif|jpg|jpeg|png)$': '<rootDir>/build/jestStyleMock.js', // }, };
一、简单测试结构
function sum(a,b){ return a+b; } it('adds 1 + 2 to equal 3', () => { expect(sum(1, 2)).toBe(3); });
二、异步的测试结构
async function sum (a,b){ return a+b; } it('adds 1 + 2 to equal 3',async () => { const total = await sum(1,2) expect(total).toBe(3); });
三、Mock Function 结构
function forEach(items, callback) { for (let index = 0; index < items.length; index++) { callback(items[index]); } } const mockCallback = jest.fn(x => 42 + x); forEach([0, 1], mockCallback); // 能够 mockCallback.mock 访问 mockCallback 状态
一、jest.fn 用来建立一个 mock function
二、mockCallback.mock 能够访问 mock function 的状态
mock 的属性:
calls : 调用的参数数组,保存了每次调用的入参
calls.length : 调用次数
calls[0][0] : 第一次调用的时候的第一个参数
results:调用的结果数组
results[0].value : 第一次调用的返回结果
执行 mock function
const myMock = jest.fn(); console.log(myMock()); // > undefined myMock .mockReturnValueOnce(10) .mockReturnValueOnce('x') .mockReturnValue(true); console.log(myMock(), myMock(), myMock(), myMock());
//10 x true
一、用 mockRetrunValueOnce(value) 来预先设置函数的返回值
二、mymock() 返回预先设置的值
异步请求的数据模拟
let fetch = { get:() =>{} } jest.mock(fetch) fetch.get.mockResolvedValue({data:{},status:0}) fetch.get(url,options) // {data:{},status:0}
describe(message,()=>{}) : 建立块
it(message,()=>{}) : 测试单元
expect(value) : 注入测试单元
expect.extend({}) : 拓展 expect 方法
expect.extend({ toBeBetween(received, arg1, arg2) { const min = arg1; const max = arg2; if (received > min && received < max) { return { message: '', pass: true, }; } return { message: `received is between in ${min} - ${max}`, pass: true, }; }, }); expect(99).toBeBetween(1,100)
expect.anything() : 返回除了 null 和 undefined 意外的任何类型数据
expect.any(Number/String) : 任意 数字/字符串
expect.assertions(num) : 肯定在块中调用几回异步
toBe(value) : 等于
toHaveBeenCalled() : 肯定函数调用
toHaveBeenCalledTime(number) : 肯定被调用的次数
toHaveBeenCalledWith(arg1,arg2) :取保调用的函数的值
toHaveBeenNthCalledWith(num,arg2) : 确保第几个参数
toHaveRetruned() :确保有返回值
toHave[:Nth]RetrunedWith([:num,]arg) : 确保某一个有返回值
toContain(item) : 数组中是否包含
toMatch(regex) :正则表达式
enzyme 一共有四个大的 api ( shallow 、mount 、render 、selectors )。
经过这四个 api 能够对 react 组件进行操做。
咱们能够经过相似于 jquery 的操做来进行 test 。