jest学习笔记

1. 安装

1.1 最新版本的jest安装需要babel 7.X
npm install babel-jest jest --save-dev
1.2 babel 6.X的可安装以下版本或者升级babel
npm install babel-jest@23.6.0 jest@23.6.0 --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(<Link page="http://www.facebook.com">Facebook</Link>)
    .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 babel-jest@23.6.0 jest@23.6.0 babel-plugin-transform-require-ignore enzyme enzyme-adapter-react-16.1 enzyme-to-json --save-dev
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容

  • 一、测试DOM 1.操作DOM 简单例子: 使用npx jest测试执行,结果为passed 2.测试DOM原理 ...
    One_Hund阅读 2,237评论 0 0
  • 你也可以使用Jest的“匹配器”来测试数据。有很多不同的匹配器,所以这篇文章只会介绍最常用的几种。 普通匹配 最简...
    人头原子弹阅读 1,084评论 0 0
  • 使用匹配器 使用不同匹配器可以测试输入输出的值是否符合预期。下面介绍一些常见的匹配器。 普通匹配器 最简单的测试值...
    Gopal阅读 12,024评论 0 6
  • 一、起步 # 1、挂载 2、生成jest.config.js配置文件 安装相关依赖 babel配置 jest通过b...
    热心市民在线搬砖阅读 1,317评论 0 0
  • 01 在有一次户外活动的车上,自我介绍环节里头,我跟大家说,每次出行我都喜欢一个人出行,因为,如果你带着朋友出来,...
    灵女侠阅读 775评论 0 0