跳到主要内容

常用匹配器

一、基础匹配器

.toBe(value)

匹配数字,字符等完全相等,不能匹配对象。

const can = {
name: 'pamplemousse',
ounces: 12,
};

describe('the can', () => {
test('has 12 ounces', () => {
expect(can.ounces).toBe(12);
});

test('has a sophisticated name', () => {
expect(can.name).toBe('pamplemousse');
});
});

.toEqual(value)

匹配两者内容相等,对象

const can1 = {
flavor: 'grapefruit',
ounces: 12,
};
const can2 = {
flavor: 'grapefruit',
ounces: 12,
};

describe('the La Croix cans on my desk', () => {
test('have all the same properties', () => {
expect(can1).toEqual(can2);
});
test('are not the exact same can', () => {
expect(can1).not.toBe(can2);
});
});

.toStrictEqual(value)

匹配对象拥有相同的类型和结构

class LaCroix {
constructor(flavor) {
this.flavor = flavor;
}
}

describe('the La Croix cans on my desk', () => {
test('are not semantically the same', () => {
expect(new LaCroix('lemon')).toEqual({flavor: 'lemon'});
expect(new LaCroix('lemon')).not.toStrictEqual({flavor: 'lemon'});
});
});

.toContain(item)

匹配数组或字符串里是否包含某个具体项

test('the flavor list contains lime', () => {
expect(getAllFlavors()).toContain('lime');
});

.toContainEqual(item)

匹配数组或对象里,是否包含某个对象

describe('my beverage', () => {
test('is delicious and not sour', () => {
const myBeverage = {delicious: true, sour: false};
expect(myBeverages()).toContainEqual(myBeverage);
});
});

二、特殊值匹配器

.toBeNull()

匹配是否为Null

function bloop() {
return null;
}

test('bloop returns null', () => {
expect(bloop()).toBeNull();
});

// 等价于 .toBe(null)
// 但.toBeNull的报错提示更友好,推荐使用

.toBeUndefined()

匹配是否为 未定义,undefined,或一个函数是否返回undefined

test('the best drink for octopus flavor is undefined', () => {
expect(bestDrinkForFlavor('octopus')).toBeUndefined();
});

.toBeDefined()

匹配对象是否定义了

test('there is a new flavor idea', () => {
expect(fetchNewFlavorIdea()).toBeDefined();
});

.toBeNaN()

匹配是否为NaN

test('passes when value is NaN', () => {
expect(NaN).toBeNaN();
expect(1).not.toBeNaN();
});

.toBeTruthy()

匹配是否为真

drinkSomeLaCroix();
if (thirstInfo()) {
drinkMoreLaCroix();
}
test('drinking La Croix leads to having thirst info', () => {
drinkSomeLaCroix();
expect(thirstInfo()).toBeTruthy();
});

.toBeFalsy()

匹配是否为假

drinkSomeLaCroix();
if (!getErrors()) {
drinkMoreLaCroix();
}
test('drinking La Croix does not lead to errors', () => {
drinkSomeLaCroix();
expect(getErrors()).toBeFalsy();
});

// 在javascript中有这六种假值 ‘false’、‘0’、‘''’、‘null’,‘undefined’、‘NaN’
// 其他值都为真

.not

用于其他匹配器之前,表示相反

test('the best flavor is not coconut', () => {
expect(bestLaCroixFlavor()).not.toBe('coconut');
expect().toBeTurthy
expect().not.toBeFalsy()
});

三、数字匹配器

.toBeGreaterThan(number | bigint)

匹配是否大于某个数

test('ounces per can is more than 10', () => {
expect(ouncesPerCan()).toBeGreaterThan(10);
});

.toBeGreaterThanOrEqual(number | bigint)

匹配是否大于等于某个数

test('ounces per can is at least 12', () => {
expect(ouncesPerCan()).toBeGreaterThanOrEqual(12);
});

.toBeLessThan()

匹配是否小于某个数

test('ounces per can is less than 20', () => {
expect(ouncesPerCan()).toBeLessThan(20);
});

.toBeLessThanOrEqual()

匹配是否小于等于某个数

test('ounces per can is at most 12', () => {
expect(ouncesPerCan()).toBeLessThanOrEqual(12);
});

.toBeCloseTo(number, numDigits?)

匹配浮点数是否靠近指定值

// 测试浮点数,错误示例。使用.toBe没法正确匹配。
test('adding works sanely with decimals', () => {
// 在javascript里 0.1 + 0.2 实际等于‘0.30000000000000004’这是二进制计数导致的误差。
expect(0.2 + 0.1).toBe(0.3); // Fails!
});

// 正确示例
test('adding works sanely with decimals', () => {
// 精确到小数点后五位
expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
});

四、异步匹配器

.resolves

用于promise承诺成功后,获取返回的数据

test('resolves to lemon', () => {
// make sure to add a return statement
return expect(Promise.resolve('lemon')).resolves.toBe('lemon');
});


// 支持async与await
test('resolves to lemon', async () => {
await expect(Promise.resolve('lemon')).resolves.toBe('lemon');
await expect(Promise.resolve('lemon')).resolves.not.toBe('octopus');
});

.rejects

用于promise承诺失败后,获取异常情况

test('rejects to octopus', () => {
// make sure to add a return statement
return expect(Promise.reject(new Error('octopus'))).rejects.toThrow(
'octopus',
);
});

// 支持async与await
test('rejects to octopus', async () => {
await expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus');
});

五、函数匹配器

.toHaveBeenCalled()

匹配某个函数是否被调用

function drinkAll(callback, flavour) {
if (flavour !== 'octopus') {
callback(flavour);
}
}

describe('drinkAll', () => {
test('drinks something lemon-flavoured', () => {
const drink = jest.fn();
drinkAll(drink, 'lemon');
expect(drink).toHaveBeenCalled();
});

test('does not drink something octopus-flavoured', () => {
const drink = jest.fn();
drinkAll(drink, 'octopus');
expect(drink).not.toHaveBeenCalled();
});
});

.toHaveBeenCalledTimes(number)

匹配函数被调用的准确次数

test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenCalledTimes(2);
});

.toHaveBeenCalledWith(arg1, arg2, ...)

匹配函数调用的具体参数

test('registration applies correctly to orange La Croix', () => {
const beverage = new LaCroix('orange');
register(beverage);
const f = jest.fn();
applyToAll(f);
expect(f).toHaveBeenCalledWith(beverage);
});

.toHaveBeenLastCalledWith(arg1, arg2, ...)

匹配调用函数的最后一个参数

test('applying to all flavors does mango last', () => {
const drink = jest.fn();
applyToAllFlavors(drink);
expect(drink).toHaveBeenLastCalledWith('mango');
});

.toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....)

匹配某个函数,第几次调用时,是否为指定的某个参数

test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenNthCalledWith(1, 'lemon');
expect(drink).toHaveBeenNthCalledWith(2, 'octopus');
});

.toHaveReturned()

匹配某个函数是否成功返回

test('drinks returns', () => {
const drink = jest.fn(() => true);
drink();
expect(drink).toHaveReturned();
});

.toHaveReturnedTimes(number)

匹配某个函数成功返回的次数

test('drink returns twice', () => {
const drink = jest.fn(() => true);
drink();
drink();
expect(drink).toHaveReturnedTimes(2);
});

.toHaveReturnedWith(value)

匹配某个函数是否返回了指定的值

test('drink returns La Croix', () => {
const beverage = {name: 'La Croix'};
const drink = jest.fn(beverage => beverage.name);
drink(beverage);
expect(drink).toHaveReturnedWith('La Croix');
});

.toHaveLastReturnedWith(value)

匹配某个函数,最后一次执行返回的值,是否为指定的值

test('drink returns La Croix (Orange) last', () => {
const beverage1 = {name: 'La Croix (Lemon)'};
const beverage2 = {name: 'La Croix (Orange)'};
const drink = jest.fn(beverage => beverage.name);
drink(beverage1);
drink(beverage2);
expect(drink).toHaveLastReturnedWith('La Croix (Orange)');
});

.toHaveNthReturnedWith(nthCall, value)

匹配某函数,指定次数返回的值,是否为指定的值

test('drink returns expected nth calls', () => {
const beverage1 = {name: 'La Croix (Lemon)'};
const beverage2 = {name: 'La Croix (Orange)'};
const drink = jest.fn(beverage => beverage.name);
drink(beverage1);
drink(beverage2);
expect(drink).toHaveNthReturnedWith(1, 'La Croix (Lemon)');
expect(drink).toHaveNthReturnedWith(2, 'La Croix (Orange)');
});

六、对象匹配器

.toHaveLength(number)

匹配某个对象是否有length属性,具体为几。可用于检查数组和字符串大小

expect([1, 2, 3]).toHaveLength(3);
expect('abc').toHaveLength(3);
expect('').not.toHaveLength(5);

.toHaveProperty(keyPath, value?)

匹配某个对象里是否含有某个字段属性,值是否正确。可通过数组,字符串路径的方式,查看深层数据

// 待测试样例数据
const houseForSale = {
bath: true,
bedrooms: 4,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
area: 20,
wallColor: 'white',
'nice.oven': true,
},
'ceiling.height': 2,
};

test('this house has my desired features', () => {
// 检查是否有‘bath’属性
expect(houseForSale).toHaveProperty('bath');
// 检查是否有‘bedrooms’属性,值是否为4
expect(houseForSale).toHaveProperty('bedrooms', 4);
// 检查是否没有‘pool’属性
expect(houseForSale).not.toHaveProperty('pool');

// 使用点表示法的深度引用---用点描述路径
// 检查‘kitchen.area’路径属性是否存在,值是否为20
expect(houseForSale).toHaveProperty('kitchen.area', 20);
expect(houseForSale).toHaveProperty('kitchen.amenities', [
'oven',
'stove',
'washer',
]);
expect(houseForSale).not.toHaveProperty('kitchen.open');

// 使用包含keyPath的数组进行深度引用--用数组描述路径
// 检查‘kitchen.area’路径的属性是否存在,值是否为20
expect(houseForSale).toHaveProperty(['kitchen', 'area'], 20);
expect(houseForSale).toHaveProperty(
['kitchen', 'amenities'],
['oven', 'stove', 'washer'],
);
expect(houseForSale).toHaveProperty(['kitchen', 'amenities', 0], 'oven');
expect(houseForSale).toHaveProperty(['kitchen', 'nice.oven']);
expect(houseForSale).not.toHaveProperty(['kitchen', 'open']);

// 引用键本身带有点的键
expect(houseForSale).toHaveProperty(['ceiling.height'], 'tall');
});

.toBeInstanceOf(Class)

匹配一个对象是否是一个类的实例

class A {}
expect(new A()).toBeInstanceOf(A);
expect(() => {}).toBeInstanceOf(Function);
expect(new A()).toBeInstanceOf(Function); // throws

.toMatch(regexp | string)

检查字符串是否与正则表达式相匹配

describe('an essay on the best flavor', () => {
test('mentions grapefruit', () => {
expect(essayOnTheBestFlavor()).toMatch(/grapefruit/);
expect(essayOnTheBestFlavor()).toMatch(new RegExp('grapefruit'));
});
});

describe('grapefruits are healthy', () => {
test('grapefruits are a fruit', () => {
expect('grapefruits').toMatch('fruit');
});
});

.toMatchObject(object)

匹配一个对象,是否是某个对象的子集

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);
});



describe('toMatchObject applied to arrays', () => {
test('the number of elements must match exactly', () => {
expect([{foo: 'bar'}, {baz: 1}]).toMatchObject([{foo: 'bar'}, {baz: 1}]);
});

test('.toMatchObject is called for each elements, so extra object properties are okay', () => {
expect([{foo: 'bar'}, {baz: 1, extra: 'quux'}]).toMatchObject([
{foo: 'bar'},
{baz: 1},
]);
});
});

.toMatchSnapshot(propertyMatchers?, hint?)

匹配快照与最新的一个值比较

.toMatchInlineSnapshot(propertyMatchers?, inlineSnapshot)

匹配快照与最近的一个值比较

七、报错匹配器

.toThrow(error?)

匹配是否有报错信息

test('throws on octopus', () => {
expect(() => {
drinkFlavor('octopus');
}).toThrow();
});
// 您必须将代码包装在函数中,否则将无法捕获错误,断言将失败。

function drinkFlavor(flavor) {
if (flavor == 'octopus') {
throw new DisgustingFlavorError('yuck, octopus flavor');
}
// Do some other stuff
}

test('throws on octopus', () => {
function drinkOctopus() {
drinkFlavor('octopus');
}
// Test that the error message says "yuck" somewhere: these are equivalent
expect(drinkOctopus).toThrowError(/yuck/);
expect(drinkOctopus).toThrowError('yuck');
// Test the exact error message
expect(drinkOctopus).toThrowError(/^yuck, octopus flavor$/);
expect(drinkOctopus).toThrowError(new Error('yuck, octopus flavor'));
// Test that we get a DisgustingFlavorError
expect(drinkOctopus).toThrowError(DisgustingFlavorError);
});

.toThrowErrorMatchingSnapshot(hint?)

测试匹配函数在调用时抛出匹配最近快照的错误

function drinkFlavor(flavor) {
if (flavor == 'octopus') {
throw new DisgustingFlavorError('yuck, octopus flavor');
}
// Do some other stuff
}

test('throws on octopus', () => {
function drinkOctopus() {
drinkFlavor('octopus');
}
expect(drinkOctopus).toThrowErrorMatchingSnapshot();
});

exports[`drinking flavors throws on octopus 1`] = `"yuck, octopus flavor"`;

.toThrowErrorMatchingInlineSnapsÏhot(inlineSnapshot)

测试函数在调用时抛出匹配最近快照的错误