jest学习笔记

1. 安装

1.1 最新版本的jest安装需要babel 7.X
npm install babel-jest jest --save-dev
1.2 babel 6.X的可安装以下版本或者升级babel
npm install [email protected] [email protected] --save-dev
1.3 jest不支持import语法 要安装
npm install babel-plugin-transform-es2015-modules-commonjs --save-dev

2. 配置packge.json

script: {
    "test": "jest"
}

3. 初试demo

3.1 新建一个sum.js并编写
export function sum(a, b) {
    return a + b;
};
3.2 新建一个sum.test.js并编写
import {sum} from "./sum.js";

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});
3.3 在命令行输入
npm run jest

命令行打印为

PASS  test/sum.test.js
√ adds 1 + 2 to equal 3 (3ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.829s
Ran all test suites.

4. 语法学习

4.1 expect
//示例语法
expect( 2 + 2 ).toBe( 4 )
  • expect( 2 + 2)返回一个期望的对象

4.2 toBe
//示例语法
expect( 2 + 2 ).toBe( 4 )
  • toBe() 是一个匹配器. 他是调用Object.is 来测试精确相等.
  • 不能用来匹配浮点数相加,因为浮点数有舍入误差
  • 如果想测试对象的值,请使用toEqual

4.3 toEqual(递归检查对象或数组的每个字段是否相等)
//示例语法
const data = {one: 1};
data['two'] = 2;
expect(data).toEqual({one: 1, two: 2});

4.4 not (类似于非运算符)
//示例语法
expect( 2 + 2 ).not.toBe( 0 )

4.5 匹配null、false、if语句的真假
  • toBeNull 只匹配 null
  • toBeUndefined 只匹配 undefined
  • toBeDefined 与 toBeUndefined 相反
  • toBeTruthy 匹配任何 if 语句为真
  • toBeFalsy 匹配任何 if 语句为假

4.6 toBeCloseTo(用于匹配浮点数相加(比如float))

4.7 toMatch( 用正则来匹配字符串)
//示例代码
test('but there is a "stop" in Christoph', () => {
  expect('Christoph').toMatch(/stop/);
});

4.8 toContain(检查一个数组或可迭代对象是否包含某个特定项)
const shoppingList = [
  'diapers',
  'kleenex',
  'trash bags',
  'paper towels',
  'beer',
];

test('the shopping list has beer on it', () => {
  expect(shoppingList).toContain('beer');
  expect(new Set(shoppingList)).toContain('beer');
});
4.9 toThrow(测试的特定函数抛出一个错误)
function compileAndroidCode() {
  throw new Error('you are using the wrong JDK');
}

test('compiling android goes as expected', () => {
  expect(compileAndroidCode).toThrow();
  expect(compileAndroidCode).toThrow(Error);

  // You can also use the exact error message or a regexp
  expect(compileAndroidCode).toThrow('you are using the wrong JDK');
  expect(compileAndroidCode).toThrow(/JDK/);
});

5 回调函数callBack

export function fetchData(cb) {
    setTimeout(() => {
        cb("peanut butter");
    }, 1000)
};
5.1 错误示例
import {fetchData} from "./sum.js";

test('cb prams jest', done => {
    function cb(data) {
            expect(data).toBe('peanut butter');
    fetchData(cb);
});
  1. 这样测试会在执行完同步的fetchDate时,jest就会认为本次测试已经执行完,date不等于"peanut butter",而报错.
  2. 官方解释: 默认情况下,Jest 测试一旦执行到末尾就会完成。 那意味着该测试将不会按预期工作
5.1 正确示例
import {fetchData} from "./sum.js";

test('cb jest', done => {
    function cb(data) {
        try{
            expect(data).toBe('peanut butter');
            done();
        } catch (error) {
            done(error);
        }
    }

    fetchData(cb);
});

使用单个参数调用 done,而不是将测试放在一个空参数的函数。 Jest会等done回调函数执行结束后,结束测试。

6. Promises( 如果承诺被拒绝,则测试将自动失败)

6.1 原始方法
export function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("peanut butter")
        },500)
    })
};
import {fetchData} from "./sum.js";

test('promise jest', () => {
    return fetchData().then(data => {
        expect(data).toBe('peanut butter');
    });
});

注意: 一定不要忘记把 promise 作为返回值⸺如果你忘了 return 语句的话,在 fetchData 返回的这个 promise 被 resolve、then() 有机会执行之前,测试就已经被视为已经完成了。

6.2 .resolves / .rejects
export function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("peanut butter")
        },500)
    })
};
import {fetchData} from "./sum.js";

test('promise jest', () => {
    return expect(fetchData()).resolves.toBe('peanut butter');
});

一定不要忘记return!!!

test('the fetch fails with an error', () => {
  return expect(fetchData()).rejects.toMatch('error');
});
6.3 async和await方案(最爽)
export function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("peanut butter")
        },500)
    })
};
import {fetchData} from "./sum.js";

test('async/auaiw jest', async () => {
    const data = await fetchData();
    expect(data).toBe("peanut butter")
});

7. 作用域(describe)

  1. 类似于js的花括号,形成自己的作用域
  2. 当 before 和 after 的块在 describe 块内部时,则其只适用于该 describe 块内的测试

8. 执行顺序

9. 快照

import React from 'react';
import Link from '../Link.react';
import renderer from 'react-test-renderer';

it('renders correctly', () => {
  const tree = renderer
    .create(Facebook)
    .toJSON();
  expect(tree).toMatchSnapshot();
});

9.1 更新快照

jest --updateSnapshot

10. 异步示例(不会)

11. 计时器模拟

11.1 模拟计时器

// timerGame.js
'use strict';
function timerGame(callback) {
  console.log('Ready....go!');
  setTimeout(() => {
    console.log("Time's up -- stop!");
    callback && callback();
  }, 1000);
}
module.exports = timerGame;
// __tests__/timerGame-test.js
'use strict';
jest.useFakeTimers(); // 模拟定时器运行语句
test('waits 1 second before ending the game', () => {
  const timerGame = require('../timerGame');
  timerGame();
  // 匹配被调用几次
  expect(setTimeout).toHaveBeenCalledTimes(1); 
  // 匹配调用的时间间隔
  expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 1000);
});
  • 可以通过jest.useFakeTimers()来模拟计时器函数
  • 如果你需要在一个文件或一个描述块中运行多次测试,可以在每次测试前手动添加jest.useFakeTimers();或者在beforeEach中添加,如果不这样做的话将导致内部的计时器不被重置。

11.2 检测计时器的callback是否被执行

jest.useFakeTimers(); // 模拟计时器
test('calls the callback after 1 second', () => {
  const timerGame = require('./sum');
  const callback = jest.fn();
  timerGame(callback);
  // 在这个时间点,定时器的回调不应该被执行
  expect(callback).not.toBeCalled();
  // “快进”时间使得所有定时器回调被执行
  jest.runAllTimers();
  // 现在回调函数应该被调用了!
  expect(callback).toBeCalled();
  // cb应该只被执行了1次
  expect(callback).toHaveBeenCalledTimes(1);
});

11.3 其他语法

  • jest.runOnlyPendingTimers(); 运行待定计时器
  • 按时间提前计时器
 // “快进”时间,使得所有定时器回调都被执行
  jest.advanceTimersByTime(1000);

12. 手动模拟

cnpm install [email protected] [email protected] babel-plugin-transform-require-ignore enzyme enzyme-adapter-react-16.1 enzyme-to-json --save-dev

你可能感兴趣的:(jest学习笔记)