Jest學習記錄
一、安裝
npm isntall jest --global # 全局
npm install --save-dev jest # 項目
二、概念
1. Matchers
toBe, toEqual, not
test('two plus two is four', () => {
expect(2 + 2).toBe(4);
});
toBe 使用Object.is()來精確匹配
只想檢查值得話使用toEqual()
not用來取反
test('object assignment', () => {
const data = {one: 1};
data['two'] = 2;
expect(data).toEqual({one: 1, two: 2});
});
test('not zero', () => {
let a = 1;
let b = 3;
expect(a + b).not.toBe(0);
});
Truthiness
如何區分null,undefined和false
- toBeNull
- toBeUndefined
- toBeDefined
- toBeTruthy
- toBeFalsy
數字
對於浮點數使用toBeCloseTo()
test('two plus two', () => {
const value = 2 + 2;
expect(value).toBeGreaterThan(3);
expect(value).toBeGreaterThanOrEqual(3.5);
expect(value).toBeLessThan(5);
expect(value).toBeLessThanOrEqual(4.5);
// float
const v = 0.1 + 0.2;
expect(v).toBeCloseTo(0.3);
})
字符串
toMatch()匹配正則表達式
test('there is a "stop" in the word', function () {
expect('Christoph').toMatch(/stop/);
})
Array & Iterables
toContain()是否包含
const arr = [1,3,5,7,9];
test('not contain 6', function () {
arr.not.toContain(6);
})
Exceptions
toThrow()測試報錯
function myCode(){
throw new Error('any error');
}
test('any error', function () {
expect(myCode).toThrow();
})
2. Asynchronous
Callback
done()等待回調完成
test('the data is peanut butter', done => {
function callback (data) {
try {
expect(data).toBe('peanut butter');
done(); // jest callback flag
} catch (error) {
done(error);
}
}
fetchData(callback);
})
Promise
返回一個Promise
test('peanut butter', () => {
return fetchData().then(data => {
expect(data).toBe('peanut butter');
});
});
test('the fetch fails with an error', () => {
expect.assertions(1);
return fetchData().catch(e => expect(e).toMatch('error'));
});
.resolves/.rejects
test('peanut butter', () => {
return expect(fetchData()).resolves.toBe('peanut butter');
});
test('error', () => {
return expect(fetchData()).rejects.toMatch('error');
});
async/await
最簡潔,最推薦
test('peanut butter', async () => {
const data = await fetchData();
expect(data).toBe('peanut butter');
});
test('error', async() => {
expect.assertions(1);
try {
await fetchData();
} catch (e) {
expect(e).toMatch('error');
}
});
混合使用
test('data', async() => {
await expect(fetchData()).resolves.toBe('data');
});
test('error', async() => {
await expect(fetchData()).rejects.toThrow('error');
});
3. Setup & Teardown
多次重複設置
beforeEach( () => {
// do something
});
afterEach( () => {
// do something
});
一次性設置
beforAll( () => { /* ... */});
afterAll( () => { /* ... */});
describe
在真正測試開始之前,先執行所有describe handlers
僅運行某一條測試
test.only('only test', () => { /*...*/});
4. Mock Function
.mock
所有mock函數都有.mock
屬性,保存調用相關信息
const myMock = jest.fn();
myMock.mock.instances; // this指向
myMock.mock.calls; // 調用,參數信息
myMock.mock.results; // 返回值
mockReturnValue 模擬返回值
連續傳遞風格continuation-passing style
mockReturnValueOnce()
const filterTestFun = jest.fn();
filterTestFun.mockReturnValueOnce(true).mockReturnValue(false);
模擬模塊
測試方法而不實際調用API(使測試變得緩慢,脆弱)
// users.js
import axios from 'axios';
class Users {
static all() {
return axios.get('/user.json').then(resp => resp.data);
}
}
export default Users;
// users.test.js
import axios from 'axios';
import Users from './users.js';
jest.mock('axios');
test('should fetch users', () => {
const users = [{name: 'Bob'}];
const resp = {data: users};
axios.get.mockResolvedValue(resp);
return Users.all().then(data => expect(data).toEqual(users));
});
模擬實現
jest.fn() 和 mockImplementationOnce()
const myMockFn = jest
.fn(() => 'default)
.mockImplementationOnce( () => 'first call')
.mockImplementationOnce( () => 'second call');
// 返回this的鏈式調用
jest.fn().mockReturnThis();
jest.fn(function () {
return this;
})
具名模擬
mockName(‘name’)
const myMockFn = jest
.fn()
.mockName('mockFunction');