Jest 實在是很方便仰美,上手簡單妻率,幾乎零配置。記錄一下學習 Jest matchers盟戏。附上大部分說明及示例绪妹。
普通匹配器
- toBe - toBe 使用 Object.is 來測試是否完全相等
- .not - 用來測試相反的用例
- .toEqual - 如果你想檢查某個對象的值,請改用 toEqual。
toBe
最簡單的測試值的方法是看是否精確匹配。
test('two plus two is four', () => {
expect(2 + 2).toBe(4);
});
toEqual
如果你想檢查某個對象的值累舷,請改用 toEqual。
test('object assignment', () => {
const data = {one: 1};
data['two'] = 2;
expect(data).toEqual({one: 1, two: 2});
});
.not
用來測試相反的用例
test('null', () => {
const n = null;
expect(n).not.toBeUndefined();
expect(n).not.toBeTruthy();
});
布爾值匹配器
- toBeNull 只匹配 null
- toBeUndefined 只匹配 undefined
- toBeDefined 與 toBeUndefined 相反
- toBeTruthy 匹配任何 if 語句為真
- toBeFalsy 匹配任何 if 語句為假
test('null', () => {
const n = null;
expect(n).toBeNull();
expect(n).toBeDefined();
expect(n).not.toBeUndefined();
expect(n).not.toBeTruthy();
expect(n).toBeFalsy();
});
test('zero', () => {
const z = 0;
expect(z).not.toBeNull();
expect(z).toBeDefined();
expect(z).not.toBeUndefined();
expect(z).not.toBeTruthy();
expect(z).toBeFalsy();
});
數(shù)字匹配器
- .toBeGreaterThan() - 大于
- .toBeGreaterThanOrEqual() 大于等于
- .toBeLessThan() - 小于
- .toBeLessThanOrEqual() - 小于等于
- .toBeCloseTo() - 浮點數(shù)比較
toBeGreaterThan婶肩、toBeGreaterThanOrEqual、toBeLessThan貌夕、toBeLessThanOrEqual
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);
// toBe 和 toEqual 對于數(shù)字來說是一樣的
expect(value).toBe(4);
expect(value).toEqual(4);
});
.toBeCloseTo()
對于比較浮點數(shù)的相等律歼,應該使用 toBeCloseTo
test('兩個浮點數(shù)字相加', () => {
const value = 0.1 + 0.2; // 0.30000000000000004
expect(value).toBe(0.3); // 這句會報錯,因為 js 浮點數(shù)有舍入誤差
expect(value).toBeCloseTo(0.3); // 這句可以運行
});
字符串匹配器
- toMatch - 正則表達式的字符
- .toHaveLength(number) - 判斷一個有長度的對象的長度
toMatch
正則表達式的字符
test('there is no I in team', () => {
expect('team').not.toMatch(/I/);
});
test('but there is a "stop" in Christoph', () => {
expect('Christoph').toMatch(/stop/);
});
.toHaveLength(number)
判斷一個有長度的對象的長度
expect([1, 2, 3]).toHaveLength(3);
expect('abc').toHaveLength(3);
expect('').not.toHaveLength(5);
數(shù)組匹配器
- .toContain(item) - 判斷數(shù)組是否包含特定子項
- .toContainEqual(item) - 判斷數(shù)組中是否包含一個特定對象
.toContain
判斷數(shù)組是否包含特定子項
const shoppingList = [
'diapers',
'kleenex',
'trash bags',
'paper towels',
'beer',
];
test('購物清單(shopping list)里面有啤酒(beer)', () => {
expect(shoppingList).toContain('beer');
});
.toContainEqual(item)
可以判斷數(shù)組中是否包含一個特定對象蜂嗽,類似 toEqual 與 toContain 的結合
function myBeverages() {
return [
{delicious: true, sour: false},
{delicious: false, sour: true}
]
}
test('is delicious and not sour', () => {
const myBeverage = {delicious: true, sour: false};
expect(myBeverages()).toContainEqual(myBeverage);
});
對象匹配器
- .toMatchObject(object) - 判斷一個對象嵌套的 key 下面的 value 類型
- .toHaveProperty(keyPath, value) - 判斷在指定的 path 下是否有這個屬性
.toMatchObject(object)
判斷一個對象嵌套的 key 下面的 value 類型苗膝,需要傳入一個對象。
const houseForSale = {
bath: true,
bedrooms: 4,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
area: 20,
wallColor: 'white',
},
};
const desiredHouse = {
bath: true,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
wallColor: expect.stringMatching(/white|yellow/),
},
};
test('the house has my desired features', () => {
expect(houseForSale).toMatchObject(desiredHouse);
});
.toHaveProperty(keyPath, value)
判斷在指定的 path 下是否有這個屬性植旧,嵌套的 path 可以用 '.'分割辱揭,也可以用數(shù)組。
// Object containing house features to be tested
const houseForSale = {
bath: true,
bedrooms: 4,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
area: 20,
wallColor: 'white',
},
};
test('this house has my desired features', () => {
// Simple Referencing
expect(houseForSale).toHaveProperty('bath');
expect(houseForSale).toHaveProperty('bedrooms', 4);
expect(houseForSale).not.toHaveProperty('pool');
// Deep referencing using dot notation
expect(houseForSale).toHaveProperty('kitchen.area', 20);
expect(houseForSale).toHaveProperty('kitchen.amenities', [
'oven',
'stove',
'washer',
]);
expect(houseForSale).not.toHaveProperty('kitchen.open');
// Deep referencing using an array containing the keyPath
expect(houseForSale).toHaveProperty(['kitchen', 'area'], 20);
expect(houseForSale).toHaveProperty(
['kitchen', 'amenities'],
['oven', 'stove', 'washer'],
);
expect(houseForSale).toHaveProperty(['kitchen', 'amenities', 0], 'oven');
expect(houseForSale).not.toHaveProperty(['kitchen', 'open']);
});
自定義匹配器
使用expect.extend將自己的匹配器添加到Jest病附。自定義匹配器需要返回一個包含兩個key 的對象
{
pass:false //‘布爾值’问窃,
message: () => 'message string' //‘函數(shù),該函數(shù)返回一個提示信息’
}
expect.extend({
toBeDivisibleBy(received, argument) {
const pass = received % argument == 0;
if (pass) {
return {
message: () =>
`expected ${received} not to be divisible by ${argument}`,
pass: true,
};
} else {
return {
message: () => `expected ${received} to be divisible by ${argument}`,
pass: false,
};
}
},
});
test('even and odd numbers', () => {
expect(100).toBeDivisibleBy(2);
expect(101).not.toBeDivisibleBy(2);
});
這些幫助函數(shù)可以在自定義匹配器中的this中找到:
- this.isNot
- this.equals(a, b)
- this.utils(matcherHint, printExpected and printReceived)
其他
- toThrow - 要測試的特定函數(shù)會在調用時拋出一個錯誤
- .resolves 和 .rejects - 用來測試 promise
- .toHaveBeenCalled() - 用來判斷一個函數(shù)是否被調用過
- .toHaveBeenCalledTimes(number) - 判斷函數(shù)被調用過幾次
toThrow
要測試的特定函數(shù)會在調用時拋出一個錯誤
function compileAndroidCode() {
throw new ConfigError('you are using the wrong JDK');
}
test('compiling android goes as expected', () => {
expect(compileAndroidCode).toThrow();
expect(compileAndroidCode).toThrow(ConfigError);
// You can also use the exact error message or a regexp
expect(compileAndroidCode).toThrow('you are using the wrong JDK');
expect(compileAndroidCode).toThrow(/JDK/);
});
.resolves 和 .rejects
用來測試 promise
//resolves
test('resolves to lemon', () => {
// make sure to add a return statement
return expect(Promise.resolve('lemon')).resolves.toBe('lemon');
});
//rejects
test('resolves to lemon', async () => {
await expect(Promise.resolve('lemon')).resolves.toBe('lemon');
await expect(Promise.resolve('lemon')).resolves.not.toBe('octopus');
});
.toHaveBeenCalled()
.toHaveBeenCalled() 也有個別名是.toBeCalled()完沪,用來判斷一個函數(shù)是否被調用過域庇。
describe('drinkAll', () => {
test('drinks something lemon-flavored', () => {
const drink = jest.fn();
drinkAll(drink, 'lemon');
expect(drink).toHaveBeenCalled();
});
test('does not drink something octopus-flavored', () => {
const drink = jest.fn();
drinkAll(drink, 'octopus');
expect(drink).not.toHaveBeenCalled();
});
});
.toHaveBeenCalledTimes(number)
和 toHaveBeenCalled 類似,判斷函數(shù)被調用過幾次覆积。
test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenCalledTimes(2);
});