期望
当你编写测试时,你经常需要检查值是否满足某些条件。expect
使你可以访问许多 "matchers",让你验证不同的事物。
¥When you're writing tests, you often need to check that values meet certain conditions. expect
gives you access to a number of "matchers" that let you validate different things.
有关 Jest 社区维护的其他 Jest 匹配器,请查看 jest-extended
。
¥For additional Jest matchers maintained by the Jest Community check out jest-extended
.
仅当你显式导入 Jest API 时,此页面中的 TypeScript 示例才会按照文档说明的方式工作:
¥The TypeScript examples from this page will only work as documented if you explicitly import Jest APIs:
import {expect, jest, test} from '@jest/globals';
有关如何使用 TypeScript 设置 Jest 的详细信息,请参阅 入门 指南。
¥Consult the Getting Started guide for details on how to setup Jest with TypeScript.
参考
¥Reference
- 期望
- 修饰符
- 匹配器
.toBe(value)
.toHaveBeenCalled()
.toHaveBeenCalledTimes(number)
.toHaveBeenCalledWith(arg1, arg2, ...)
.toHaveBeenLastCalledWith(arg1, arg2, ...)
.toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....)
.toHaveReturned()
.toHaveReturnedTimes(number)
.toHaveReturnedWith(value)
.toHaveLastReturnedWith(value)
.toHaveNthReturnedWith(nthCall, value)
.toHaveLength(number)
.toHaveProperty(keyPath, value?)
.toBeCloseTo(number, numDigits?)
.toBeDefined()
.toBeFalsy()
.toBeGreaterThan(number | bigint)
.toBeGreaterThanOrEqual(number | bigint)
.toBeLessThan(number | bigint)
.toBeLessThanOrEqual(number | bigint)
.toBeInstanceOf(Class)
.toBeNull()
.toBeTruthy()
.toBeUndefined()
.toBeNaN()
.toContain(item)
.toContainEqual(item)
.toEqual(value)
.toMatch(regexp | string)
.toMatchObject(object)
.toMatchSnapshot(propertyMatchers?, hint?)
.toMatchInlineSnapshot(propertyMatchers?, inlineSnapshot)
.toStrictEqual(value)
.toThrow(error?)
.toThrowErrorMatchingSnapshot(hint?)
.toThrowErrorMatchingInlineSnapshot(inlineSnapshot)
- 不对称匹配器
expect.anything()
expect.any(constructor)
expect.arrayContaining(array)
expect.not.arrayContaining(array)
expect.closeTo(number, numDigits?)
expect.objectContaining(object)
expect.not.objectContaining(object)
expect.stringContaining(string)
expect.not.stringContaining(string)
expect.stringMatching(string | regexp)
expect.not.stringMatching(string | regexp)
- 断言计数
- 扩展实用程序
期望
¥Expect
expect(value)
每次要测试值时都会使用 expect
函数。你很少会单独调用 expect
。相反,你将使用 expect
和 "matcher" 函数来断言某个值的某些内容。
¥The expect
function is used every time you want to test a value. You will rarely call expect
by itself. Instead, you will use expect
along with a "matcher" function to assert something about a value.
通过一个例子更容易理解这一点。假设你有一个方法 bestLaCroixFlavor()
,它应该返回字符串 'grapefruit'
。你可以通过以下方式进行测试:
¥It's easier to understand this with an example. Let's say you have a method bestLaCroixFlavor()
which is supposed to return the string 'grapefruit'
. Here's how you would test that:
test('the best flavor is grapefruit', () => {
expect(bestLaCroixFlavor()).toBe('grapefruit');
});
在本例中,toBe
是匹配器函数。下面记录了许多不同的匹配器函数,可以帮助你测试不同的东西。
¥In this case, toBe
is the matcher function. There are a lot of different matcher functions, documented below, to help you test different things.
expect
的参数应该是代码生成的值,并且匹配器的任何参数都应该是正确的值。如果你把它们混合起来,你的测试仍然可以工作,但是失败的测试的错误消息看起来会很奇怪。
¥The argument to expect
should be the value that your code produces, and any argument to the matcher should be the correct value. If you mix them up, your tests will still work, but the error messages on failing tests will look strange.
修饰符
¥Modifiers
.not
如果你知道如何测试某些东西,.not
可以让你测试它的反面。例如,此代码测试最好的 La Croix 风味不是椰子:
¥If you know how to test something, .not
lets you test its opposite. For example, this code tests that the best La Croix flavor is not coconut:
test('the best flavor is not coconut', () => {
expect(bestLaCroixFlavor()).not.toBe('coconut');
});
.resolves
使用 resolves
来解开已履行 promise 的值,以便可以链接任何其他匹配器。如果 promise 被拒绝,则断言失败。
¥Use resolves
to unwrap the value of a fulfilled promise so any other matcher can be chained. If the promise is rejected the assertion fails.
例如,此代码测试 Promise 是否解析以及结果值是否为 'lemon'
:
¥For example, this code tests that the promise resolves and that the resulting value is 'lemon'
:
test('resolves to lemon', () => {
// make sure to add a return statement
return expect(Promise.resolve('lemon')).resolves.toBe('lemon');
});
由于你仍在测试 Promise,因此测试仍然是异步的。因此,你需要通过返回未封装的断言来 让杰斯特稍等一下。
¥Since you are still testing promises, the test is still asynchronous. Hence, you will need to tell Jest to wait by returning the unwrapped assertion.
或者,你可以将 async/await
与 .resolves
结合使用:
¥Alternatively, you can use async/await
in combination with .resolves
:
test('resolves to lemon', async () => {
await expect(Promise.resolve('lemon')).resolves.toBe('lemon');
await expect(Promise.resolve('lemon')).resolves.not.toBe('octopus');
});
.rejects
使用 .rejects
来解开被拒绝的 Promise 的原因,以便可以链接任何其他匹配器。如果 promise 得到履行,则断言失败。
¥Use .rejects
to unwrap the reason of a rejected promise so any other matcher can be chained. If the promise is fulfilled the assertion fails.
例如,此代码测试 Promise 是否因原因 'octopus'
而拒绝:
¥For example, this code tests that the promise rejects with reason 'octopus'
:
test('rejects to octopus', () => {
// make sure to add a return statement
return expect(Promise.reject(new Error('octopus'))).rejects.toThrow(
'octopus',
);
});
由于你仍在测试 Promise,因此测试仍然是异步的。因此,你需要通过返回未封装的断言来 让杰斯特稍等一下。
¥Since you are still testing promises, the test is still asynchronous. Hence, you will need to tell Jest to wait by returning the unwrapped assertion.
或者,你可以将 async/await
与 .rejects
结合使用。
¥Alternatively, you can use async/await
in combination with .rejects
.
test('rejects to octopus', async () => {
await expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus');
});
匹配器
¥Matchers
.toBe(value)
使用 .toBe
比较原始值或检查对象实例的引用标识。它调用 Object.is
来比较值,这比 ===
严格相等运算符更适合测试。
¥Use .toBe
to compare primitive values or to check referential identity of object instances. It calls Object.is
to compare values, which is even better for testing than ===
strict equality operator.
例如,此代码将验证 can
对象的一些属性:
¥For example, this code will validate some properties of the can
object:
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');
});
});
不要将 .toBe
与浮点数一起使用。例如,由于四舍五入的原因,JavaScript 中的 0.2 + 0.1
并不严格等于 0.3
。如果你有浮点数,请尝试使用 .toBeCloseTo
。
¥Don't use .toBe
with floating-point numbers. For example, due to rounding, in JavaScript 0.2 + 0.1
is not strictly equal to 0.3
. If you have floating point numbers, try .toBeCloseTo
instead.
尽管 .toBe
匹配器会检查引用身份,但如果断言失败,它会报告值的深度比较。如果属性之间的差异不能帮助你理解测试失败的原因,特别是在报告很大的情况下,那么你可以将比较移至 expect
函数中。例如,断言元素是否是同一实例:
¥Although the .toBe
matcher checks referential identity, it reports a deep comparison of values if the assertion fails. If differences between properties do not help you to understand why a test fails, especially if the report is large, then you might move the comparison into the expect
function. For example, to assert whether or not elements are the same instance:
-
将
expect(received).toBe(expected)
重写为expect(Object.is(received, expected)).toBe(true)
¥rewrite
expect(received).toBe(expected)
asexpect(Object.is(received, expected)).toBe(true)
-
将
expect(received).not.toBe(expected)
重写为expect(Object.is(received, expected)).toBe(false)
¥rewrite
expect(received).not.toBe(expected)
asexpect(Object.is(received, expected)).toBe(false)
.toHaveBeenCalled()
也在别名下:.toBeCalled()
¥Also under the alias: .toBeCalled()
使用 .toHaveBeenCalled
确保调用了模拟函数。
¥Use .toHaveBeenCalled
to ensure that a mock function was called.
例如,假设你有一个 drinkAll(drink, flavour)
函数,它接受 drink
函数并将其应用于所有可用的饮料。你可能需要检查 drink
是否被调用。你可以使用此测试套件来做到这一点:
¥For example, let's say you have a drinkAll(drink, flavour)
function that takes a drink
function and applies it to all available beverages. You might want to check that drink
gets called. You can do that with this test suite:
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)
也在别名下:.toBeCalledTimes(number)
¥Also under the alias: .toBeCalledTimes(number)
使用 .toHaveBeenCalledTimes
确保模拟函数被调用的确切次数。
¥Use .toHaveBeenCalledTimes
to ensure that a mock function got called exact number of times.
例如,假设你有一个 drinkEach(drink, Array<flavor>)
函数,它接受 drink
函数并将其应用于传递的饮料数组。你可能想要检查 Drink 函数被调用的确切次数。你可以使用此测试套件来做到这一点:
¥For example, let's say you have a drinkEach(drink, Array<flavor>)
function that takes a drink
function and applies it to array of passed beverages. You might want to check that drink function was called exact number of times. You can do that with this test suite:
test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenCalledTimes(2);
});
.toHaveBeenCalledWith(arg1, arg2, ...)
也在别名下:.toBeCalledWith()
¥Also under the alias: .toBeCalledWith()
使用 .toHaveBeenCalledWith
确保使用特定参数调用模拟函数。使用 .toEqual
使用的相同算法检查参数。
¥Use .toHaveBeenCalledWith
to ensure that a mock function was called with specific arguments. The arguments are checked with the same algorithm that .toEqual
uses.
例如,假设你可以使用 register
函数注册饮料,而 applyToAll(f)
应该将函数 f
应用于所有已注册的饮料。为了确保它有效,你可以这样写:
¥For example, let's say that you can register a beverage with a register
function, and applyToAll(f)
should apply the function f
to all registered beverages. To make sure this works, you could write:
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, ...)
也在别名下:.lastCalledWith(arg1, arg2, ...)
¥Also under the alias: .lastCalledWith(arg1, arg2, ...)
如果你有模拟函数,则可以使用 .toHaveBeenLastCalledWith
来测试上次调用它时使用的参数。例如,假设你有一个 applyToAllFlavors(f)
函数,它将 f
应用于一堆风味,并且你希望确保当你调用它时,它操作的最后一个风味是 'mango'
。你可以写:
¥If you have a mock function, you can use .toHaveBeenLastCalledWith
to test what arguments it was last called with. For example, let's say you have a applyToAllFlavors(f)
function that applies f
to a bunch of flavors, and you want to ensure that when you call it, the last flavor it operates on is 'mango'
. You can write:
test('applying to all flavors does mango last', () => {
const drink = jest.fn();
applyToAllFlavors(drink);
expect(drink).toHaveBeenLastCalledWith('mango');
});
.toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....)
也在别名下:.nthCalledWith(nthCall, arg1, arg2, ...)
¥Also under the alias: .nthCalledWith(nthCall, arg1, arg2, ...)
如果你有模拟函数,则可以使用 .toHaveBeenNthCalledWith
来测试第 n 次调用它的参数。例如,假设你有一个 drinkEach(drink, Array<flavor>)
函数,它将 f
应用于一堆风味,并且你希望确保在调用它时,它操作的第一个风味是 'lemon'
,第二个是 'octopus'
。你可以写:
¥If you have a mock function, you can use .toHaveBeenNthCalledWith
to test what arguments it was nth called with. For example, let's say you have a drinkEach(drink, Array<flavor>)
function that applies f
to a bunch of flavors, and you want to ensure that when you call it, the first flavor it operates on is 'lemon'
and the second one is 'octopus'
. You can write:
test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenNthCalledWith(1, 'lemon');
expect(drink).toHaveBeenNthCalledWith(2, 'octopus');
});
第 n 个参数必须是从 1 开始的正整数。
¥The nth argument must be positive integer starting from 1.
.toHaveReturned()
也在别名下:.toReturn()
¥Also under the alias: .toReturn()
如果你有一个模拟函数,你可以使用 .toHaveReturned
来测试该模拟函数是否至少成功返回一次(即,没有抛出错误)。例如,假设你有一个返回 true
的模拟 drink
。你可以写:
¥If you have a mock function, you can use .toHaveReturned
to test that the mock function successfully returned (i.e., did not throw an error) at least one time. For example, let's say you have a mock drink
that returns true
. You can write:
test('drinks returns', () => {
const drink = jest.fn(() => true);
drink();
expect(drink).toHaveReturned();
});
.toHaveReturnedTimes(number)
也在别名下:.toReturnTimes(number)
¥Also under the alias: .toReturnTimes(number)
使用 .toHaveReturnedTimes
确保模拟函数成功返回(即,没有抛出错误)准确的次数。任何抛出错误的模拟函数调用都不会计入该函数返回的次数。
¥Use .toHaveReturnedTimes
to ensure that a mock function returned successfully (i.e., did not throw an error) an exact number of times. Any calls to the mock function that throw an error are not counted toward the number of times the function returned.
例如,假设你有一个返回 true
的模拟 drink
。你可以写:
¥For example, let's say you have a mock drink
that returns true
. You can write:
test('drink returns twice', () => {
const drink = jest.fn(() => true);
drink();
drink();
expect(drink).toHaveReturnedTimes(2);
});
.toHaveReturnedWith(value)
也在别名下:.toReturnWith(value)
¥Also under the alias: .toReturnWith(value)
使用 .toHaveReturnedWith
确保模拟函数返回特定值。
¥Use .toHaveReturnedWith
to ensure that a mock function returned a specific value.
例如,假设你有一个模拟 drink
,它返回所喝饮料的名称。你可以写:
¥For example, let's say you have a mock drink
that returns the name of the beverage that was consumed. You can write:
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)
也在别名下:.lastReturnedWith(value)
¥Also under the alias: .lastReturnedWith(value)
使用 .toHaveLastReturnedWith
测试模拟函数最后返回的具体值。如果对模拟函数的最后一次调用引发了错误,则无论你提供什么值作为预期返回值,此匹配器都将失败。
¥Use .toHaveLastReturnedWith
to test the specific value that a mock function last returned. If the last call to the mock function threw an error, then this matcher will fail no matter what value you provided as the expected return value.
例如,假设你有一个模拟 drink
,它返回所喝饮料的名称。你可以写:
¥For example, let's say you have a mock drink
that returns the name of the beverage that was consumed. You can write:
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)
也在别名下:.nthReturnedWith(nthCall, value)
¥Also under the alias: .nthReturnedWith(nthCall, value)
使用 .toHaveNthReturnedWith
测试模拟函数第 n 次调用返回的特定值。如果对模拟函数的第 n 次调用抛出错误,则无论你提供什么值作为预期返回值,此匹配器都将失败。
¥Use .toHaveNthReturnedWith
to test the specific value that a mock function returned for the nth call. If the nth call to the mock function threw an error, then this matcher will fail no matter what value you provided as the expected return value.
例如,假设你有一个模拟 drink
,它返回所喝饮料的名称。你可以写:
¥For example, let's say you have a mock drink
that returns the name of the beverage that was consumed. You can write:
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)');
});
第 n 个参数必须是从 1 开始的正整数。
¥The nth argument must be positive integer starting from 1.
.toHaveLength(number)
使用 .toHaveLength
检查对象是否具有 .length
属性并且该属性已设置为某个数值。
¥Use .toHaveLength
to check that an object has a .length
property and it is set to a certain numeric value.
这对于检查数组或字符串大小特别有用。
¥This is especially useful for checking arrays or strings size.
expect([1, 2, 3]).toHaveLength(3);
expect('abc').toHaveLength(3);
expect('').not.toHaveLength(5);
.toHaveProperty(keyPath, value?)
使用 .toHaveProperty
检查所提供的引用 keyPath
处的属性是否存在于某个对象。要检查对象中的深度嵌套属性,你可以使用 点符号 或包含深度引用的 keyPath 的数组。
¥Use .toHaveProperty
to check if property at provided reference keyPath
exists for an object. For checking deeply nested properties in an object you may use dot notation or an array containing the keyPath for deep references.
你可以提供可选的 value
参数来比较接收到的属性值(递归地比较对象实例的所有属性,也称为深度相等,如 toEqual
匹配器)。
¥You can provide an optional value
argument to compare the received property value (recursively for all properties of object instances, also known as deep equality, like the toEqual
matcher).
以下示例包含具有嵌套属性的 houseForSale
对象。我们使用 toHaveProperty
来检查对象中各种属性是否存在及其值。
¥The following example contains a houseForSale
object with nested properties. We are using toHaveProperty
to check for the existence and values of various properties in the object.
// Object containing house features to be tested
const houseForSale = {
bath: true,
bedrooms: 4,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
area: 20,
wallColor: 'white',
'nice.oven': true,
},
livingroom: {
amenities: [
{
couch: [
['large', {dimensions: [20, 20]}],
['small', {dimensions: [10, 10]}],
],
},
],
},
'ceiling.height': 2,
};
test('this house has my desired features', () => {
// Example 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).toHaveProperty(
'livingroom.amenities[0].couch[0][1].dimensions[0]',
20,
);
expect(houseForSale).toHaveProperty(['kitchen', 'nice.oven']);
expect(houseForSale).not.toHaveProperty(['kitchen', 'open']);
// Referencing keys with dot in the key itself
expect(houseForSale).toHaveProperty(['ceiling.height'], 'tall');
});
.toBeCloseTo(number, numDigits?)
使用 toBeCloseTo
比较浮点数是否近似相等。
¥Use toBeCloseTo
to compare floating point numbers for approximate equality.
可选的 numDigits
参数限制小数点后要检查的位数。对于默认值 2
,测试标准为 Math.abs(expected - received) < 0.005
(即 10 ** -2 / 2
)。
¥The optional numDigits
argument limits the number of digits to check after the decimal point. For the default value 2
, the test criterion is Math.abs(expected - received) < 0.005
(that is, 10 ** -2 / 2
).
直观的相等比较通常会失败,因为十进制(以 10 为基数)值的算术在有限精度的二进制(以 2 为基数)表示中通常会出现舍入误差。例如,此测试失败:
¥Intuitive equality comparisons often fail, because arithmetic on decimal (base 10) values often have rounding errors in limited precision binary (base 2) representation. For example, this test fails:
test('adding works sanely with decimals', () => {
expect(0.2 + 0.1).toBe(0.3); // Fails!
});
它失败了,因为在 JavaScript 中,0.2 + 0.1
实际上是 0.30000000000000004
。
¥It fails because in JavaScript, 0.2 + 0.1
is actually 0.30000000000000004
.
例如,此测试以 5 位精度通过:
¥For example, this test passes with a precision of 5 digits:
test('adding works sanely with decimals', () => {
expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
});
因为浮点错误是 toBeCloseTo
解决的问题,所以它不支持大整数值。
¥Because floating point errors are the problem that toBeCloseTo
solves, it does not support big integer values.
.toBeDefined()
使用 .toBeDefined
检查变量是否未定义。例如,如果你想检查函数 fetchNewFlavorIdea()
是否返回某些内容,你可以编写:
¥Use .toBeDefined
to check that a variable is not undefined. For example, if you want to check that a function fetchNewFlavorIdea()
returns something, you can write:
test('there is a new flavor idea', () => {
expect(fetchNewFlavorIdea()).toBeDefined();
});
你可以编写 expect(fetchNewFlavorIdea()).not.toBe(undefined)
,但更好的做法是避免在代码中直接引用 undefined
。
¥You could write expect(fetchNewFlavorIdea()).not.toBe(undefined)
, but it's better practice to avoid referring to undefined
directly in your code.
.toBeFalsy()
当你不关心值是什么并且希望确保布尔上下文中的值为 false 时,请使用 .toBeFalsy
。例如,假设你有一些如下所示的应用代码:
¥Use .toBeFalsy
when you don't care what a value is and you want to ensure a value is false in a boolean context. For example, let's say you have some application code that looks like:
drinkSomeLaCroix();
if (!getErrors()) {
drinkMoreLaCroix();
}
你可能不关心 getErrors
返回什么,特别是 - 它可能会返回 false
、null
或 0
,并且你的代码仍然可以工作。所以如果你想测试喝了一些 La Croix 后没有错误,你可以这样写:
¥You may not care what getErrors
returns, specifically - it might return false
, null
, or 0
, and your code would still work. So if you want to test there are no errors after drinking some La Croix, you could write:
test('drinking La Croix does not lead to errors', () => {
drinkSomeLaCroix();
expect(getErrors()).toBeFalsy();
});
在 JavaScript 中,有六个假值:false
、0
、''
、null
、undefined
和 NaN
。其他一切都是真实的。
¥In JavaScript, there are six falsy values: false
, 0
, ''
, null
, undefined
, and NaN
. Everything else is truthy.
.toBeGreaterThan(number | bigint)
使用 toBeGreaterThan
比较 received > expected
的数字或大整数值。例如,测试 ouncesPerCan()
返回的值是否大于 10 盎司:
¥Use toBeGreaterThan
to compare received > expected
for number or big integer values. For example, test that ouncesPerCan()
returns a value of more than 10 ounces:
test('ounces per can is more than 10', () => {
expect(ouncesPerCan()).toBeGreaterThan(10);
});
.toBeGreaterThanOrEqual(number | bigint)
使用 toBeGreaterThanOrEqual
比较 received >= expected
的数字或大整数值。例如,测试 ouncesPerCan()
返回的值至少为 12 盎司:
¥Use toBeGreaterThanOrEqual
to compare received >= expected
for number or big integer values. For example, test that ouncesPerCan()
returns a value of at least 12 ounces:
test('ounces per can is at least 12', () => {
expect(ouncesPerCan()).toBeGreaterThanOrEqual(12);
});
.toBeLessThan(number | bigint)
使用 toBeLessThan
比较 received < expected
的数字或大整数值。例如,测试 ouncesPerCan()
返回的值是否小于 20 盎司:
¥Use toBeLessThan
to compare received < expected
for number or big integer values. For example, test that ouncesPerCan()
returns a value of less than 20 ounces:
test('ounces per can is less than 20', () => {
expect(ouncesPerCan()).toBeLessThan(20);
});
.toBeLessThanOrEqual(number | bigint)
使用 toBeLessThanOrEqual
比较 received <= expected
的数字或大整数值。例如,测试 ouncesPerCan()
返回的值最多为 12 盎司:
¥Use toBeLessThanOrEqual
to compare received <= expected
for number or big integer values. For example, test that ouncesPerCan()
returns a value of at most 12 ounces:
test('ounces per can is at most 12', () => {
expect(ouncesPerCan()).toBeLessThanOrEqual(12);
});
.toBeInstanceOf(Class)
使用 .toBeInstanceOf(Class)
检查对象是否是类的实例。该匹配器在下面使用 instanceof
。
¥Use .toBeInstanceOf(Class)
to check that an object is an instance of a class. This matcher uses instanceof
underneath.
class A {}
expect(new A()).toBeInstanceOf(A);
expect(() => {}).toBeInstanceOf(Function);
expect(new A()).toBeInstanceOf(Function); // throws
.toBeNull()
.toBeNull()
与 .toBe(null)
相同,但错误消息更好一些。因此,当你想检查某些内容是否为空时,请使用 .toBeNull()
。
¥.toBeNull()
is the same as .toBe(null)
but the error messages are a bit nicer. So use .toBeNull()
when you want to check that something is null.
function bloop() {
return null;
}
test('bloop returns null', () => {
expect(bloop()).toBeNull();
});
.toBeTruthy()
当你不关心值是什么并且希望确保值在布尔上下文中为 true 时,请使用 .toBeTruthy
。例如,假设你有一些如下所示的应用代码:
¥Use .toBeTruthy
when you don't care what a value is and you want to ensure a value is true in a boolean context. For example, let's say you have some application code that looks like:
drinkSomeLaCroix();
if (thirstInfo()) {
drinkMoreLaCroix();
}
你可能不关心 thirstInfo
返回什么,特别是 - 它可能会返回 true
或复杂的对象,并且你的代码仍然可以工作。因此,如果你想在喝了一些 La Croix 后测试 thirstInfo
是否真实,你可以这样写:
¥You may not care what thirstInfo
returns, specifically - it might return true
or a complex object, and your code would still work. So if you want to test that thirstInfo
will be truthy after drinking some La Croix, you could write:
test('drinking La Croix leads to having thirst info', () => {
drinkSomeLaCroix();
expect(thirstInfo()).toBeTruthy();
});
在 JavaScript 中,有六个假值:false
、0
、''
、null
、undefined
和 NaN
。其他一切都是真实的。
¥In JavaScript, there are six falsy values: false
, 0
, ''
, null
, undefined
, and NaN
. Everything else is truthy.
.toBeUndefined()
使用 .toBeUndefined
检查变量是否未定义。例如,如果你想检查函数 bestDrinkForFlavor(flavor)
是否为 'octopus'
口味返回 undefined
,因为没有好的章鱼味饮料:
¥Use .toBeUndefined
to check that a variable is undefined. For example, if you want to check that a function bestDrinkForFlavor(flavor)
returns undefined
for the 'octopus'
flavor, because there is no good octopus-flavored drink:
test('the best drink for octopus flavor is undefined', () => {
expect(bestDrinkForFlavor('octopus')).toBeUndefined();
});
你可以编写 expect(bestDrinkForFlavor('octopus')).toBe(undefined)
,但更好的做法是避免在代码中直接引用 undefined
。
¥You could write expect(bestDrinkForFlavor('octopus')).toBe(undefined)
, but it's better practice to avoid referring to undefined
directly in your code.
.toBeNaN()
当检查值是 NaN
时使用 .toBeNaN
。
¥Use .toBeNaN
when checking a value is NaN
.
test('passes when value is NaN', () => {
expect(NaN).toBeNaN();
expect(1).not.toBeNaN();
});
.toContain(item)
当你想要检查某个项目是否在数组中时,请使用 .toContain
。为了测试数组中的项目,这使用了 ===
,即严格的相等检查。.toContain
还可以检查一个字符串是否是另一个字符串的子字符串。
¥Use .toContain
when you want to check that an item is in an array. For testing the items in the array, this uses ===
, a strict equality check. .toContain
can also check whether a string is a substring of another string.
例如,如果 getAllFlavors()
返回一个口味数组,并且你想确保 lime
位于其中,则可以编写:
¥For example, if getAllFlavors()
returns an array of flavors and you want to be sure that lime
is in there, you can write:
test('the flavor list contains lime', () => {
expect(getAllFlavors()).toContain('lime');
});
该匹配器还接受其他可迭代对象,例如字符串、集合、节点列表和 HTML 集合。
¥This matcher also accepts others iterables such as strings, sets, node lists and HTML collections.
.toContainEqual(item)
当你想要检查数组中是否包含具有特定结构和值的项目时,请使用 .toContainEqual
。为了测试数组中的项目,此匹配器递归地检查所有字段的相等性,而不是检查对象标识。
¥Use .toContainEqual
when you want to check that an item with a specific structure and values is contained in an array. For testing the items in the array, this matcher recursively checks the equality of all fields, rather than checking for object identity.
describe('my beverage', () => {
test('is delicious and not sour', () => {
const myBeverage = {delicious: true, sour: false};
expect(myBeverages()).toContainEqual(myBeverage);
});
});
.toEqual(value)
使用 .toEqual
递归比较对象实例的所有属性(也称为 "deep" 相等性)。它调用 Object.is
来比较原始值,这比 ===
严格相等运算符更适合测试。
¥Use .toEqual
to compare recursively all properties of object instances (also known as "deep" equality). It calls Object.is
to compare primitive values, which is even better for testing than ===
strict equality operator.
例如,.toEqual
和 .toBe
在此测试套件中的行为不同,因此所有测试都通过:
¥For example, .toEqual
and .toBe
behave differently in this test suite, so all the tests pass:
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);
});
});
toEqual
忽略具有 undefined
属性、undefined
数组项、数组稀疏性或对象类型不匹配的对象键。要考虑这些,请改用 .toStrictEqual
。
¥toEqual
ignores object keys with undefined
properties, undefined
array items, array sparseness, or object type mismatch. To take these into account use .toStrictEqual
instead.
.toEqual
不会对两个错误执行深度相等检查。仅错误的 message
属性被视为相等。建议使用 .toThrow
匹配器来测试错误。
¥.toEqual
won't perform a deep equality check for two errors. Only the message
property of an Error is considered for equality. It is recommended to use the .toThrow
matcher for testing against errors.
如果属性之间的差异不能帮助你理解测试失败的原因,特别是在报告很大的情况下,那么你可以将比较移至 expect
函数中。例如,使用 Buffer
类的 equals
方法来断言缓冲区是否包含相同的内容:
¥If differences between properties do not help you to understand why a test fails, especially if the report is large, then you might move the comparison into the expect
function. For example, use equals
method of Buffer
class to assert whether or not buffers contain the same content:
-
将
expect(received).toEqual(expected)
重写为expect(received.equals(expected)).toBe(true)
¥rewrite
expect(received).toEqual(expected)
asexpect(received.equals(expected)).toBe(true)
-
将
expect(received).not.toEqual(expected)
重写为expect(received.equals(expected)).toBe(false)
¥rewrite
expect(received).not.toEqual(expected)
asexpect(received.equals(expected)).toBe(false)
.toMatch(regexp | string)
使用 .toMatch
检查字符串是否与正则表达式匹配。
¥Use .toMatch
to check that a string matches a regular expression.
例如,你可能不知道 essayOnTheBestFlavor()
到底返回什么,但你知道它是一个非常长的字符串,并且子字符串 grapefruit
应该在其中的某个位置。你可以使用以下方法进行测试:
¥For example, you might not know what exactly essayOnTheBestFlavor()
returns, but you know it's a really long string, and the substring grapefruit
should be in there somewhere. You can test this with:
describe('an essay on the best flavor', () => {
test('mentions grapefruit', () => {
expect(essayOnTheBestFlavor()).toMatch(/grapefruit/);
expect(essayOnTheBestFlavor()).toMatch(new RegExp('grapefruit'));
});
});
该匹配器还接受一个字符串,它将尝试匹配该字符串:
¥This matcher also accepts a string, which it will try to match:
describe('grapefruits are healthy', () => {
test('grapefruits are a fruit', () => {
expect('grapefruits').toMatch('fruit');
});
});
.toMatchObject(object)
使用 .toMatchObject
检查 JavaScript 对象是否与对象属性的子集匹配。它将接收的对象与预期对象中不存在的属性进行匹配。
¥Use .toMatchObject
to check that a JavaScript object matches a subset of the properties of an object. It will match received objects with properties that are not in the expected object.
你还可以传递对象数组,在这种情况下,仅当接收到的数组中的每个对象与预期数组中的相应对象匹配(在上述 toMatchObject
意义上)时,该方法才会返回 true。如果你想检查两个数组的元素数量是否匹配,这非常有用,这与 arrayContaining
不同,后者允许在接收的数组中包含额外的元素。
¥You can also pass an array of objects, in which case the method will return true only if each object in the received array matches (in the toMatchObject
sense described above) the corresponding object in the expected array. This is useful if you want to check that two arrays match in their number of elements, as opposed to arrayContaining
, which allows for extra elements in the received array.
你可以将属性与值或匹配器进行匹配。
¥You can match properties against values or against matchers.
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?)
这可确保值与最新快照匹配。查看 快照测试指南 了解更多信息。
¥This ensures that a value matches the most recent snapshot. Check out the Snapshot Testing guide for more information.
你可以提供可选的 propertyMatchers
对象参数,如果接收到的值是对象实例,则该参数将非对称匹配器作为预期属性子集的值。它就像 toMatchObject
,对属性子集具有灵活的标准,然后进行快照测试作为其余属性的精确标准。
¥You can provide an optional propertyMatchers
object argument, which has asymmetric matchers as values of a subset of expected properties, if the received value will be an object instance. It is like toMatchObject
with flexible criteria for a subset of properties, followed by a snapshot test as exact criteria for the rest of the properties.
你可以提供附加到测试名称的可选 hint
字符串参数。尽管 Jest 总是在快照名称末尾附加一个数字,但简短的描述性提示可能比数字更有用,可以区分单个 it
或 test
块中的多个快照。Jest 按相应 .snap
文件中的名称对快照进行排序。
¥You can provide an optional hint
string argument that is appended to the test name. Although Jest always appends a number at the end of a snapshot name, short descriptive hints might be more useful than numbers to differentiate multiple snapshots in a single it
or test
block. Jest sorts snapshots by name in the corresponding .snap
file.
.toMatchInlineSnapshot(propertyMatchers?, inlineSnapshot)
确保值与最新快照匹配。
¥Ensures that a value matches the most recent snapshot.
你可以提供可选的 propertyMatchers
对象参数,如果接收到的值是对象实例,则该参数将非对称匹配器作为预期属性子集的值。它就像 toMatchObject
,对属性子集具有灵活的标准,然后进行快照测试作为其余属性的精确标准。
¥You can provide an optional propertyMatchers
object argument, which has asymmetric matchers as values of a subset of expected properties, if the received value will be an object instance. It is like toMatchObject
with flexible criteria for a subset of properties, followed by a snapshot test as exact criteria for the rest of the properties.
第一次运行测试时,Jest 将 inlineSnapshot
字符串参数添加到测试文件中的匹配器(而不是外部 .snap
文件)。
¥Jest adds the inlineSnapshot
string argument to the matcher in the test file (instead of an external .snap
file) the first time that the test runs.
查看 内联快照 部分以获取更多信息。
¥Check out the section on Inline Snapshots for more info.
.toStrictEqual(value)
使用 .toStrictEqual
来测试对象是否具有相同的结构和类型。
¥Use .toStrictEqual
to test that objects have the same structure and type.
与 .toEqual
的区别:
¥Differences from .toEqual
:
-
检查具有
undefined
属性的键,例如{a: undefined, b: 2}
不会等于{b: 2}
;¥keys with
undefined
properties are checked, e.g.{a: undefined, b: 2}
will not equal{b: 2}
; -
考虑了
undefined
个项目,例如[2]
不会等于[2, undefined]
;¥
undefined
items are taken into account, e.g.[2]
will not equal[2, undefined]
; -
检查数组稀疏性,例如
[, 1]
不会等于[undefined, 1]
;¥array sparseness is checked, e.g.
[, 1]
will not equal[undefined, 1]
; -
检查对象类型,例如 具有字段
a
和b
的类实例不等于具有字段a
和b
的字面量对象。¥object types are checked, e.g. a class instance with fields
a
andb
will not equal a literal object with fieldsa
andb
.
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'});
});
});
.toThrow(error?)
也在别名下:.toThrowError(error?)
¥Also under the alias: .toThrowError(error?)
使用 .toThrow
来测试函数在调用时是否抛出异常。例如,如果我们想测试 drinkFlavor('octopus')
抛出异常,因为章鱼味太恶心了,不能喝,我们可以这样写:
¥Use .toThrow
to test that a function throws when it is called. For example, if we want to test that drinkFlavor('octopus')
throws, because octopus flavor is too disgusting to drink, we could write:
test('throws on octopus', () => {
expect(() => {
drinkFlavor('octopus');
}).toThrow();
});
你必须将代码封装在函数中,否则错误将不会被捕获并且断言将失败。
¥You must wrap the code in a function, otherwise the error will not be caught and the assertion will fail.
你可以提供一个可选参数来测试是否引发特定错误:
¥You can provide an optional argument to test that a specific error is thrown:
-
正则表达式:错误消息与模式匹配
¥regular expression: error message matches the pattern
-
字符串:错误消息包含子字符串
¥string: error message includes the substring
-
错误对象:错误消息等于对象的 message 属性
¥error object: error message is equal to the message property of the object
-
错误类:错误对象是类的实例
¥error class: error object is instance of class
例如,假设 drinkFlavor
的编码如下:
¥For example, let's say that drinkFlavor
is coded like this:
function drinkFlavor(flavor) {
if (flavor == 'octopus') {
throw new DisgustingFlavorError('yuck, octopus flavor');
}
// Do some other stuff
}
我们可以通过多种方式测试此错误的抛出情况:
¥We could test this error gets thrown in several ways:
test('throws on octopus', () => {
function drinkOctopus() {
drinkFlavor('octopus');
}
// Test that the error message says "yuck" somewhere: these are equivalent
expect(drinkOctopus).toThrow(/yuck/);
expect(drinkOctopus).toThrow('yuck');
// Test the exact error message
expect(drinkOctopus).toThrow(/^yuck, octopus flavor$/);
expect(drinkOctopus).toThrow(new Error('yuck, octopus flavor'));
// Test that we get a DisgustingFlavorError
expect(drinkOctopus).toThrow(DisgustingFlavorError);
});
.toThrowErrorMatchingSnapshot(hint?)
使用 .toThrowErrorMatchingSnapshot
测试函数在调用时是否抛出与最新快照匹配的错误。
¥Use .toThrowErrorMatchingSnapshot
to test that a function throws an error matching the most recent snapshot when it is called.
你可以提供附加到测试名称的可选 hint
字符串参数。尽管 Jest 总是在快照名称末尾附加一个数字,但简短的描述性提示可能比数字更有用,可以区分单个 it
或 test
块中的多个快照。Jest 按相应 .snap
文件中的名称对快照进行排序。
¥You can provide an optional hint
string argument that is appended to the test name. Although Jest always appends a number at the end of a snapshot name, short descriptive hints might be more useful than numbers to differentiate multiple snapshots in a single it
or test
block. Jest sorts snapshots by name in the corresponding .snap
file.
例如,假设你有一个 drinkFlavor
函数,每当风味为 'octopus'
时就会抛出异常,代码如下:
¥For example, let's say you have a drinkFlavor
function that throws whenever the flavor is 'octopus'
, and is coded like this:
function drinkFlavor(flavor) {
if (flavor == 'octopus') {
throw new DisgustingFlavorError('yuck, octopus flavor');
}
// Do some other stuff
}
该函数的测试将如下所示:
¥The test for this function will look this way:
test('throws on octopus', () => {
function drinkOctopus() {
drinkFlavor('octopus');
}
expect(drinkOctopus).toThrowErrorMatchingSnapshot();
});
它将生成以下快照:
¥And it will generate the following snapshot:
exports[`drinking flavors throws on octopus 1`] = `"yuck, octopus flavor"`;
查看 React 树快照测试 了解有关快照测试的更多信息。
¥Check out React Tree Snapshot Testing for more information on snapshot testing.
.toThrowErrorMatchingInlineSnapshot(inlineSnapshot)
使用 .toThrowErrorMatchingInlineSnapshot
测试函数在调用时是否抛出与最新快照匹配的错误。
¥Use .toThrowErrorMatchingInlineSnapshot
to test that a function throws an error matching the most recent snapshot when it is called.
第一次运行测试时,Jest 将 inlineSnapshot
字符串参数添加到测试文件中的匹配器(而不是外部 .snap
文件)。
¥Jest adds the inlineSnapshot
string argument to the matcher in the test file (instead of an external .snap
file) the first time that the test runs.
查看 内联快照 部分以获取更多信息。
¥Check out the section on Inline Snapshots for more info.
不对称匹配器
¥Asymmetric Matchers
expect.anything()
expect.anything()
匹配除 null
或 undefined
之外的任何内容。你可以在 toEqual
或 toHaveBeenCalledWith
中使用它而不是字面量值。例如,如果你想检查是否使用非空参数调用模拟函数:
¥expect.anything()
matches anything but null
or undefined
. You can use it inside toEqual
or toHaveBeenCalledWith
instead of a literal value. For example, if you want to check that a mock function is called with a non-null argument:
test('map calls its argument with a non-null argument', () => {
const mock = jest.fn();
[1].map(x => mock(x));
expect(mock).toHaveBeenCalledWith(expect.anything());
});
expect.any(constructor)
expect.any(constructor)
匹配使用给定构造函数创建的任何内容,或者它是传递类型的基础类型。你可以在 toEqual
或 toHaveBeenCalledWith
中使用它而不是字面量值。例如,如果你想检查是否使用数字调用模拟函数:
¥expect.any(constructor)
matches anything that was created with the given constructor or if it's a primitive that is of the passed type. You can use it inside toEqual
or toHaveBeenCalledWith
instead of a literal value. For example, if you want to check that a mock function is called with a number:
class Cat {}
function getCat(fn) {
return fn(new Cat());
}
test('randocall calls its callback with a class instance', () => {
const mock = jest.fn();
getCat(mock);
expect(mock).toHaveBeenCalledWith(expect.any(Cat));
});
function randocall(fn) {
return fn(Math.floor(Math.random() * 6 + 1));
}
test('randocall calls its callback with a number', () => {
const mock = jest.fn();
randocall(mock);
expect(mock).toHaveBeenCalledWith(expect.any(Number));
});
expect.arrayContaining(array)
expect.arrayContaining(array)
匹配接收到的数组,其中包含预期数组中的所有元素。也就是说,预期数组是接收数组的子集。因此,它匹配接收到的数组,其中包含不在预期数组中的元素。
¥expect.arrayContaining(array)
matches a received array which contains all of the elements in the expected array. That is, the expected array is a subset of the received array. Therefore, it matches a received array which contains elements that are not in the expected array.
你可以使用它来代替字面量值:
¥You can use it instead of a literal value:
-
在
toEqual
或toHaveBeenCalledWith
¥in
toEqual
ortoHaveBeenCalledWith
-
匹配
objectContaining
或toMatchObject
中的属性¥to match a property in
objectContaining
ortoMatchObject
describe('arrayContaining', () => {
const expected = ['Alice', 'Bob'];
it('matches even if received contains additional elements', () => {
expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected));
});
it('does not match if received does not contain expected elements', () => {
expect(['Bob', 'Eve']).not.toEqual(expect.arrayContaining(expected));
});
});
describe('Beware of a misunderstanding! A sequence of dice rolls', () => {
const expected = [1, 2, 3, 4, 5, 6];
it('matches even with an unexpected number 7', () => {
expect([4, 1, 6, 7, 3, 5, 2, 5, 4, 6]).toEqual(
expect.arrayContaining(expected),
);
});
it('does not match without an expected number 2', () => {
expect([4, 1, 6, 7, 3, 5, 7, 5, 4, 6]).not.toEqual(
expect.arrayContaining(expected),
);
});
});
expect.not.arrayContaining(array)
expect.not.arrayContaining(array)
匹配接收到的数组,该数组不包含预期数组中的所有元素。也就是说,预期数组不是接收数组的子集。
¥expect.not.arrayContaining(array)
matches a received array which does not contain all of the elements in the expected array. That is, the expected array is not a subset of the received array.
它是 expect.arrayContaining
的倒数。
¥It is the inverse of expect.arrayContaining
.
describe('not.arrayContaining', () => {
const expected = ['Samantha'];
it('matches if the actual array does not contain the expected elements', () => {
expect(['Alice', 'Bob', 'Eve']).toEqual(
expect.not.arrayContaining(expected),
);
});
});
expect.closeTo(number, numDigits?)
expect.closeTo(number, numDigits?)
在比较对象属性或数组项中的浮点数时很有用。如果需要比较数字,请使用 .toBeCloseTo
。
¥expect.closeTo(number, numDigits?)
is useful when comparing floating point numbers in object properties or array item. If you need to compare a number, please use .toBeCloseTo
instead.
可选的 numDigits
参数限制小数点后要检查的位数。对于默认值 2
,测试标准为 Math.abs(expected - received) < 0.005 (that is, 10 ** -2 / 2)
。
¥The optional numDigits
argument limits the number of digits to check after the decimal point. For the default value 2
, the test criterion is Math.abs(expected - received) < 0.005 (that is, 10 ** -2 / 2)
.
例如,此测试以 5 位精度通过:
¥For example, this test passes with a precision of 5 digits:
test('compare float in object properties', () => {
expect({
title: '0.1 + 0.2',
sum: 0.1 + 0.2,
}).toEqual({
title: '0.1 + 0.2',
sum: expect.closeTo(0.3, 5),
});
});
expect.objectContaining(object)
expect.objectContaining(object)
匹配任何递归匹配预期属性的接收对象。也就是说,预期对象是接收到的对象的子集。因此,它匹配接收到的对象,该对象包含预期对象中存在的属性。
¥expect.objectContaining(object)
matches any received object that recursively matches the expected properties. That is, the expected object is a subset of the received object. Therefore, it matches a received object which contains properties that are present in the expected object.
你可以使用匹配器、expect.anything()
等,而不是预期对象中的字面量属性值。
¥Instead of literal property values in the expected object, you can use matchers, expect.anything()
, and so on.
例如,假设我们希望使用 Event
对象调用 onPress
函数,而我们需要验证的是该事件具有 event.x
和 event.y
属性。我们可以通过以下方式做到这一点:
¥For example, let's say that we expect an onPress
function to be called with an Event
object, and all we need to verify is that the event has event.x
and event.y
properties. We can do that with:
test('onPress gets called with the right thing', () => {
const onPress = jest.fn();
simulatePresses(onPress);
expect(onPress).toHaveBeenCalledWith(
expect.objectContaining({
x: expect.any(Number),
y: expect.any(Number),
}),
);
});
expect.not.objectContaining(object)
expect.not.objectContaining(object)
匹配任何未递归匹配预期属性的接收对象。也就是说,预期对象不是接收到的对象的子集。因此,它匹配接收到的对象,该对象包含预期对象中不存在的属性。
¥expect.not.objectContaining(object)
matches any received object that does not recursively match the expected properties. That is, the expected object is not a subset of the received object. Therefore, it matches a received object which contains properties that are not in the expected object.
它是 expect.objectContaining
的倒数。
¥It is the inverse of expect.objectContaining
.
describe('not.objectContaining', () => {
const expected = {foo: 'bar'};
it('matches if the actual object does not contain expected key: value pairs', () => {
expect({bar: 'baz'}).toEqual(expect.not.objectContaining(expected));
});
});
expect.stringContaining(string)
如果 expect.stringContaining(string)
是包含确切预期字符串的字符串,则与接收到的值匹配。
¥expect.stringContaining(string)
matches the received value if it is a string that contains the exact expected string.
expect.not.stringContaining(string)
如果 expect.not.stringContaining(string)
不是字符串或者不包含确切的预期字符串,则 expect.not.stringContaining(string)
与接收到的值匹配。
¥expect.not.stringContaining(string)
matches the received value if it is not a string or if it is a string that does not contain the exact expected string.
它是 expect.stringContaining
的倒数。
¥It is the inverse of expect.stringContaining
.
describe('not.stringContaining', () => {
const expected = 'Hello world!';
it('matches if the received value does not contain the expected substring', () => {
expect('How are you?').toEqual(expect.not.stringContaining(expected));
});
});
expect.stringMatching(string | regexp)
如果 expect.stringMatching(string | regexp)
是与预期字符串或正则表达式匹配的字符串,则与接收到的值匹配。
¥expect.stringMatching(string | regexp)
matches the received value if it is a string that matches the expected string or regular expression.
你可以使用它来代替字面量值:
¥You can use it instead of a literal value:
-
在
toEqual
或toHaveBeenCalledWith
¥in
toEqual
ortoHaveBeenCalledWith
-
匹配
arrayContaining
中的元素¥to match an element in
arrayContaining
-
匹配
objectContaining
或toMatchObject
中的属性¥to match a property in
objectContaining
ortoMatchObject
此示例还展示了如何嵌套多个不对称匹配器,其中 expect.stringMatching
位于 expect.arrayContaining
内。
¥This example also shows how you can nest multiple asymmetric matchers, with expect.stringMatching
inside the expect.arrayContaining
.
describe('stringMatching in arrayContaining', () => {
const expected = [
expect.stringMatching(/^Alic/),
expect.stringMatching(/^[BR]ob/),
];
it('matches even if received contains additional elements', () => {
expect(['Alicia', 'Roberto', 'Evelina']).toEqual(
expect.arrayContaining(expected),
);
});
it('does not match if received does not contain expected elements', () => {
expect(['Roberto', 'Evelina']).not.toEqual(
expect.arrayContaining(expected),
);
});
});
expect.not.stringMatching(string | regexp)
如果 expect.not.stringMatching(string | regexp)
不是字符串或者是与预期字符串或正则表达式不匹配的字符串,则 expect.not.stringMatching(string | regexp)
与接收到的值匹配。
¥expect.not.stringMatching(string | regexp)
matches the received value if it is not a string or if it is a string that does not match the expected string or regular expression.
它是 expect.stringMatching
的倒数。
¥It is the inverse of expect.stringMatching
.
describe('not.stringMatching', () => {
const expected = /Hello world!/;
it('matches if the received value does not match the expected regex', () => {
expect('How are you?').toEqual(expect.not.stringMatching(expected));
});
});
断言计数
¥Assertion Count
expect.assertions(number)
expect.assertions(number)
验证测试期间是否调用了一定数量的断言。这在测试异步代码时通常很有用,以确保回调中的断言确实被调用。
¥expect.assertions(number)
verifies that a certain number of assertions are called during a test. This is often useful when testing asynchronous code, in order to make sure that assertions in a callback actually got called.
例如,假设我们有一个函数 doAsync
,它接收两个回调 callback1
和 callback2
,它将以未知的顺序异步调用这两个回调。我们可以用以下方法进行测试:
¥For example, let's say that we have a function doAsync
that receives two callbacks callback1
and callback2
, it will asynchronously call both of them in an unknown order. We can test this with:
test('doAsync calls both callbacks', () => {
expect.assertions(2);
function callback1(data) {
expect(data).toBeTruthy();
}
function callback2(data) {
expect(data).toBeTruthy();
}
doAsync(callback1, callback2);
});
expect.assertions(2)
调用确保两个回调实际上都被调用。
¥The expect.assertions(2)
call ensures that both callbacks actually get called.
expect.hasAssertions()
expect.hasAssertions()
验证在测试期间至少调用了一个断言。这在测试异步代码时通常很有用,以确保回调中的断言确实被调用。
¥expect.hasAssertions()
verifies that at least one assertion is called during a test. This is often useful when testing asynchronous code, in order to make sure that assertions in a callback actually got called.
例如,假设我们有一些处理状态的函数。prepareState
使用状态对象调用回调,validateState
在该状态对象上运行,waitOnState
返回一个等待所有 prepareState
回调完成的 promise。我们可以用以下方法进行测试:
¥For example, let's say that we have a few functions that all deal with state. prepareState
calls a callback with a state object, validateState
runs on that state object, and waitOnState
returns a promise that waits until all prepareState
callbacks complete. We can test this with:
test('prepareState prepares a valid state', () => {
expect.hasAssertions();
prepareState(state => {
expect(validateState(state)).toBeTruthy();
});
return waitOnState();
});
expect.hasAssertions()
调用确保 prepareState
回调实际上被调用。
¥The expect.hasAssertions()
call ensures that the prepareState
callback actually gets called.
扩展实用程序
¥Extend Utilities
expect.addEqualityTesters(testers)
你可以使用 expect.addEqualityTesters
添加自己的方法来测试两个对象是否相等。例如,假设你的代码中有一个表示体积的类,并且可以确定使用不同单位的两个体积是否相等。你可能希望 toEqual
(和其他相等匹配器)在与 Volume 类进行比较时使用此自定义相等方法。你可以添加自定义相等测试器,以便在比较 Volume 类时让 toEqual
检测并应用自定义逻辑:
¥You can use expect.addEqualityTesters
to add your own methods to test if two objects are equal. For example, let's say you have a class in your code that represents volume and can determine if two volumes using different units are equal. You may want toEqual
(and other equality matchers) to use this custom equality method when comparing to Volume classes. You can add a custom equality tester to have toEqual
detect and apply custom logic when comparing Volume classes:
- JavaScript
- TypeScript
// For simplicity in this example, we'll just support the units 'L' and 'mL'
export class Volume {
constructor(amount, unit) {
this.amount = amount;
this.unit = unit;
}
toString() {
return `[Volume ${this.amount}${this.unit}]`;
}
equals(other) {
if (this.unit === other.unit) {
return this.amount === other.amount;
} else if (this.unit === 'L' && other.unit === 'mL') {
return this.amount * 1000 === other.unit;
} else {
return this.amount === other.unit * 1000;
}
}
}
import {expect} from '@jest/globals';
import {Volume} from './Volume.js';
function areVolumesEqual(a, b) {
const isAVolume = a instanceof Volume;
const isBVolume = b instanceof Volume;
if (isAVolume && isBVolume) {
return a.equals(b);
} else if (isAVolume === isBVolume) {
return undefined;
} else {
return false;
}
}
expect.addEqualityTesters([areVolumesEqual]);
import {expect, test} from '@jest/globals';
import {Volume} from '../Volume.js';
import '../areVolumesEqual.js';
test('are equal with different units', () => {
expect(new Volume(1, 'L')).toEqual(new Volume(1000, 'mL'));
});
// For simplicity in this example, we'll just support the units 'L' and 'mL'
export class Volume {
public amount: number;
public unit: 'L' | 'mL';
constructor(amount: number, unit: 'L' | 'mL') {
this.amount = amount;
this.unit = unit;
}
toString(): string {
return `[Volume ${this.amount}${this.unit}]`;
}
equals(other: Volume): boolean {
if (this.unit === other.unit) {
return this.amount === other.amount;
} else if (this.unit === 'L' && other.unit === 'mL') {
return this.amount * 1000 === other.amount;
} else {
return this.amount === other.amount * 1000;
}
}
}
import {expect} from '@jest/globals';
import {Volume} from './Volume.js';
function areVolumesEqual(a: unknown, b: unknown): boolean | undefined {
const isAVolume = a instanceof Volume;
const isBVolume = b instanceof Volume;
if (isAVolume && isBVolume) {
return a.equals(b);
} else if (isAVolume === isBVolume) {
return undefined;
} else {
return false;
}
}
expect.addEqualityTesters([areVolumesEqual]);
import {expect, test} from '@jest/globals';
import {Volume} from '../Volume.js';
import '../areVolumesEqual.js';
test('are equal with different units', () => {
expect(new Volume(1, 'L')).toEqual(new Volume(1000, 'mL'));
});
自定义相等测试器 API
¥Custom equality testers API
自定义测试器是返回比较两个给定参数相等性的结果(true
或 false
)的函数,或者如果测试器不处理给定对象并希望将相等性委托给其他测试器(例如,内置相等性测试器),则返回 undefined
)。
¥Custom testers are functions that return either the result (true
or false
) of comparing the equality of the two given arguments or undefined
if the tester does not handle the given objects and wants to delegate equality to other testers (for example, the builtin equality testers).
使用 3 个参数调用自定义测试器:要比较的两个对象和自定义测试器数组(用于递归测试器,请参阅下面的部分)。
¥Custom testers are called with 3 arguments: the two objects to compare and the array of custom testers (used for recursive testers, see the section below).
这些辅助函数和属性可以在自定义测试器内的 this
上找到:
¥These helper functions and properties can be found on this
inside a custom tester:
this.equals(a, b, customTesters?)
这是一个深度相等函数,如果两个对象具有相同的值(递归地),它将返回 true
。它可以选择使用自定义相等性测试人员列表来应用深度相等性检查。如果你使用此功能,请传递给你的测试人员的自定义测试人员,以便进一步应用 equals
的相等性检查也可以使用测试作者可能已配置的自定义测试人员。有关更多详细信息,请参阅 递归自定义相等测试器 部分中的示例。
¥This is a deep-equality function that will return true
if two objects have the same values (recursively). It optionally takes a list of custom equality testers to apply to the deep equality checks. If you use this function, pass through the custom testers your tester is given so further equality checks equals
applies can also use custom testers the test author may have configured. See the example in the Recursive custom equality testers section for more details.
匹配者与测试者
¥Matchers vs Testers
匹配器是 expect
上可用的方法,例如 expect().toEqual()
。toEqual
是匹配器。测试器是匹配器使用的一种方法,用于进行相等性检查以确定对象是否相同。
¥Matchers are methods available on expect
, for example expect().toEqual()
. toEqual
is a matcher. A tester is a method used by matchers that do equality checks to determine if objects are the same.
当你想要提供测试作者可以在其测试中使用的自定义断言时,可以很好地使用自定义匹配器。例如,expect.extend
部分中的 toBeWithinRange
示例就是自定义匹配器的一个很好的示例。有时,测试作者可能想要断言两个数字完全相等,并且应该使用 toBe
。然而,其他时候,测试作者可能希望在测试中允许一定的灵活性,并且 toBeWithinRange
可能是更合适的断言。
¥Custom matchers are good to use when you want to provide a custom assertion that test authors can use in their tests. For example, the toBeWithinRange
example in the expect.extend
section is a good example of a custom matcher. Sometimes a test author may want to assert two numbers are exactly equal and should use toBe
. Other times, however, a test author may want to allow for some flexibility in their test, and toBeWithinRange
may be a more appropriate assertion.
自定义相等测试器非常适合全局扩展 Jest 匹配器,以将自定义相等逻辑应用于所有相等比较。测试作者无法为某些断言打开自定义测试器,并为其他断言关闭它们(如果需要这种行为,则应使用自定义匹配器)。例如,定义如何检查所有匹配器的两个 Volume
对象是否相等将是一个很好的自定义相等测试器。
¥Custom equality testers are good for globally extending Jest matchers to apply custom equality logic for all equality comparisons. Test authors can't turn on custom testers for certain assertions and turn them off for others (a custom matcher should be used instead if that behavior is desired). For example, defining how to check if two Volume
objects are equal for all matchers would be a good custom equality tester.
递归自定义相等测试器
¥Recursive custom equality testers
如果你的自定义相等测试器正在测试具有你想要进行深度相等的属性的对象,则应使用可供相等测试器使用的 this.equals
辅助程序。此 equals
方法与 Jest 内部用于所有深度相等比较的深度等于方法相同。它是调用自定义相等测试器的方法。它接受一组自定义相等测试器作为第三个参数。还为自定义相等测试器提供了一组自定义测试器作为其第三个参数。将此参数传递到 equals
的第三个参数中,以便对对象进行更深入的任何进一步的相等性检查也可以利用自定义相等性测试器。
¥If your custom equality testers are testing objects with properties you'd like to do deep equality with, you should use the this.equals
helper available to equality testers. This equals
method is the same deep equals method Jest uses internally for all of its deep equality comparisons. It's the method that invokes your custom equality tester. It accepts an array of custom equality testers as a third argument. Custom equality testers are also given an array of custom testers as their third argument. Pass this argument into the third argument of equals
so that any further equality checks deeper into your object can also take advantage of custom equality testers.
例如,假设你有一个 Book
类,其中包含 Author
类的数组,并且这两个类都有自定义测试器。Book
自定义测试器想要对 Author
的数组进行深度相等性检查,并传递给它的自定义测试器,因此应用 Author
自定义相等性测试器:
¥For example, let's say you have a Book
class that contains an array of Author
classes and both of these classes have custom testers. The Book
custom tester would want to do a deep equality check on the array of Author
s and pass in the custom testers given to it, so the Author
s custom equality tester is applied:
function areAuthorEqual(a, b) {
const isAAuthor = a instanceof Author;
const isBAuthor = b instanceof Author;
if (isAAuthor && isBAuthor) {
// Authors are equal if they have the same name
return a.name === b.name;
} else if (isAAuthor === isBAuthor) {
return undefined;
} else {
return false;
}
}
function areBooksEqual(a, b, customTesters) {
const isABook = a instanceof Book;
const isBBook = b instanceof Book;
if (isABook && isBBook) {
// Books are the same if they have the same name and author array. We need
// to pass customTesters to equals here so the Author custom tester will be
// used when comparing Authors
return (
a.name === b.name && this.equals(a.authors, b.authors, customTesters)
);
} else if (isABook === isBBook) {
return undefined;
} else {
return false;
}
}
expect.addEqualityTesters([areAuthorsEqual, areBooksEqual]);
请记住将相等测试器定义为常规函数而不是箭头函数,以便访问测试器上下文辅助程序(例如 this.equals
)。
¥Remember to define your equality testers as regular functions and not arrow functions in order to access the tester context helpers (e.g. this.equals
).
expect.addSnapshotSerializer(serializer)
你可以调用 expect.addSnapshotSerializer
添加格式化特定于应用的数据结构的模块。
¥You can call expect.addSnapshotSerializer
to add a module that formats application-specific data structures.
对于单个测试文件,添加的模块位于 snapshotSerializers
配置中的任何模块之前,这些模块位于内置 JavaScript 类型和 React 元素的默认快照序列化器之前。最后添加的模块是第一个测试的模块。
¥For an individual test file, an added module precedes any modules from snapshotSerializers
configuration, which precede the default snapshot serializers for built-in JavaScript types and for React elements. The last module added is the first module tested.
import serializer from 'my-serializer-module';
expect.addSnapshotSerializer(serializer);
// affects expect(value).toMatchSnapshot() assertions in the test file
如果你在各个测试文件中添加快照序列化器而不是将其添加到 snapshotSerializers
配置中:
¥If you add a snapshot serializer in individual test files instead of adding it to snapshotSerializers
configuration:
-
你使依赖显式而不是隐式。
¥You make the dependency explicit instead of implicit.
-
你可以避免可能导致你从 create-react-app 弹出的配置限制。
¥You avoid limits to configuration that might cause you to eject from create-react-app.
请参阅 配置 Jest 了解更多信息。
¥See configuring Jest for more information.
expect.extend(matchers)
你可以使用 expect.extend
将你自己的匹配器添加到 Jest。例如,假设你正在测试一个数字实用程序库,并且经常断言数字出现在其他数字的特定范围内。你可以将其抽象为 toBeWithinRange
匹配器:
¥You can use expect.extend
to add your own matchers to Jest. For example, let's say that you're testing a number utility library and you're frequently asserting that numbers appear within particular ranges of other numbers. You could abstract that into a toBeWithinRange
matcher:
- JavaScript
- TypeScript
import {expect} from '@jest/globals';
function toBeWithinRange(actual, floor, ceiling) {
if (
typeof actual !== 'number' ||
typeof floor !== 'number' ||
typeof ceiling !== 'number'
) {
throw new TypeError('These must be of type number!');
}
const pass = actual >= floor && actual <= ceiling;
if (pass) {
return {
message: () =>
`expected ${this.utils.printReceived(
actual,
)} not to be within range ${this.utils.printExpected(
`${floor} - ${ceiling}`,
)}`,
pass: true,
};
} else {
return {
message: () =>
`expected ${this.utils.printReceived(
actual,
)} to be within range ${this.utils.printExpected(
`${floor} - ${ceiling}`,
)}`,
pass: false,
};
}
}
expect.extend({
toBeWithinRange,
});
import {expect, test} from '@jest/globals';
import '../toBeWithinRange';
test('is within range', () => expect(100).toBeWithinRange(90, 110));
test('is NOT within range', () => expect(101).not.toBeWithinRange(0, 100));
test('asymmetric ranges', () => {
expect({apples: 6, bananas: 3}).toEqual({
apples: expect.toBeWithinRange(1, 10),
bananas: expect.not.toBeWithinRange(11, 20),
});
});
// optionally add a type declaration, e.g. it enables autocompletion in IDEs
declare module 'expect' {
interface AsymmetricMatchers {
toBeWithinRange(floor: number, ceiling: number): void;
}
interface Matchers<R> {
toBeWithinRange(floor: number, ceiling: number): R;
}
}
export {};
import {expect} from '@jest/globals';
import type {MatcherFunction} from 'expect';
const toBeWithinRange: MatcherFunction<[floor: unknown, ceiling: unknown]> =
// `floor` and `ceiling` get types from the line above
// it is recommended to type them as `unknown` and to validate the values
function (actual, floor, ceiling) {
if (
typeof actual !== 'number' ||
typeof floor !== 'number' ||
typeof ceiling !== 'number'
) {
throw new TypeError('These must be of type number!');
}
const pass = actual >= floor && actual <= ceiling;
if (pass) {
return {
message: () =>
// `this` context will have correct typings
`expected ${this.utils.printReceived(
actual,
)} not to be within range ${this.utils.printExpected(
`${floor} - ${ceiling}`,
)}`,
pass: true,
};
} else {
return {
message: () =>
`expected ${this.utils.printReceived(
actual,
)} to be within range ${this.utils.printExpected(
`${floor} - ${ceiling}`,
)}`,
pass: false,
};
}
};
expect.extend({
toBeWithinRange,
});
declare module 'expect' {
interface AsymmetricMatchers {
toBeWithinRange(floor: number, ceiling: number): void;
}
interface Matchers<R> {
toBeWithinRange(floor: number, ceiling: number): R;
}
}
import {expect, test} from '@jest/globals';
import '../toBeWithinRange';
test('is within range', () => expect(100).toBeWithinRange(90, 110));
test('is NOT within range', () => expect(101).not.toBeWithinRange(0, 100));
test('asymmetric ranges', () => {
expect({apples: 6, bananas: 3}).toEqual({
apples: expect.toBeWithinRange(1, 10),
bananas: expect.not.toBeWithinRange(11, 20),
});
});
匹配器的类型声明可以存在于 .d.ts
文件中或导入的 .ts
模块中(分别参见上面的 JS 和 TS 示例)。如果将声明保留在 .d.ts
文件中,请确保它包含在程序中并且是有效的模块,即它至少有一个空的 export {}
。
¥The type declaration of the matcher can live in a .d.ts
file or in an imported .ts
module (see JS and TS examples above respectively). If you keep the declaration in a .d.ts
file, make sure that it is included in the program and that it is a valid module, i.e. it has at least an empty export {}
.
你可以通过将 expect.extend
调用移至 setupFilesAfterEnv
脚本来为所有测试启用匹配器,而不是将 toBeWithinRange
模块导入到测试文件中:
¥Instead of importing toBeWithinRange
module to the test file, you can enable the matcher for all tests by moving the expect.extend
call to a setupFilesAfterEnv
script:
import {expect} from '@jest/globals';
// remember to export `toBeWithinRange` as well
import {toBeWithinRange} from './toBeWithinRange';
expect.extend({
toBeWithinRange,
});
异步匹配器
¥Async Matchers
expect.extend
还支持异步匹配器。异步匹配器返回 Promise,因此你需要等待返回值。让我们使用一个示例匹配器来说明它们的用法。我们将实现一个名为 toBeDivisibleByExternalValue
的匹配器,其中可整除的数字将从外部源中提取。
¥expect.extend
also supports async matchers. Async matchers return a Promise so you will need to await the returned value. Let's use an example matcher to illustrate the usage of them. We are going to implement a matcher called toBeDivisibleByExternalValue
, where the divisible number is going to be pulled from an external source.
expect.extend({
async toBeDivisibleByExternalValue(received) {
const externalValue = await getExternalValueFromRemoteSource();
const pass = received % externalValue == 0;
if (pass) {
return {
message: () =>
`expected ${received} not to be divisible by ${externalValue}`,
pass: true,
};
} else {
return {
message: () =>
`expected ${received} to be divisible by ${externalValue}`,
pass: false,
};
}
},
});
test('is divisible by external value', async () => {
await expect(100).toBeDivisibleByExternalValue();
await expect(101).not.toBeDivisibleByExternalValue();
});
自定义匹配器 API
¥Custom Matchers API
匹配器应该返回一个带有两个键的对象(或对象的 Promise)。pass
表示是否匹配,message
提供一个不带参数的函数,在失败时返回错误消息。因此,当 pass
为 false 时,message
应该返回 expect(x).yourMatcher()
失败时的错误消息。当 pass
为 true 时,message
应该返回 expect(x).not.yourMatcher()
失败时的错误消息。
¥Matchers should return an object (or a Promise of an object) with two keys. pass
indicates whether there was a match or not, and message
provides a function with no arguments that returns an error message in case of failure. Thus, when pass
is false, message
should return the error message for when expect(x).yourMatcher()
fails. And when pass
is true, message
should return the error message for when expect(x).not.yourMatcher()
fails.
调用匹配器时,将参数传递给 expect(x)
,然后将参数传递给 .yourMatcher(y, z)
:
¥Matchers are called with the argument passed to expect(x)
followed by the arguments passed to .yourMatcher(y, z)
:
expect.extend({
yourMatcher(x, y, z) {
return {
pass: true,
message: () => '',
};
},
});
这些辅助函数和属性可以在 this
上的自定义匹配器中找到:
¥These helper functions and properties can be found on this
inside a custom matcher:
this.isNot
一个布尔值,让你知道此匹配器是使用否定的 .not
修饰符调用的,允许你显示清晰且正确的匹配器提示(请参阅示例代码)。
¥A boolean to let you know this matcher was called with the negated .not
modifier allowing you to display a clear and correct matcher hint (see example code).
this.promise
一个字符串,允许你显示清晰且正确的匹配器提示:
¥A string allowing you to display a clear and correct matcher hint:
-
'rejects'
如果使用 Promise.rejects
修饰符调用匹配器¥
'rejects'
if matcher was called with the promise.rejects
modifier -
'resolves'
如果使用 Promise.resolves
修饰符调用匹配器¥
'resolves'
if matcher was called with the promise.resolves
modifier -
''
如果没有使用 Promise 修饰符调用匹配器¥
''
if matcher was not called with a promise modifier
this.equals(a, b, customTesters?)
这是一个深度相等函数,如果两个对象具有相同的值(递归地),它将返回 true
。它可以选择使用自定义相等性测试程序列表来应用深度相等性检查(请参阅下面的 this.customTesters
)。
¥This is a deep-equality function that will return true
if two objects have the same values (recursively). It optionally takes a list of custom equality testers to apply to the deep equality checks (see this.customTesters
below).
this.expand
一个布尔值,让你知道这个匹配器是使用 expand
选项调用的。当使用 --expand
标志调用 Jest 时,this.expand
可用于确定 Jest 是否应显示完整的差异和错误。
¥A boolean to let you know this matcher was called with an expand
option. When Jest is called with the --expand
flag, this.expand
can be used to determine if Jest is expected to show full diffs and errors.
this.utils
this.utils
上公开了许多有用的工具,主要包括 jest-matcher-utils
的导出。
¥There are a number of helpful tools exposed on this.utils
primarily consisting of the exports from jest-matcher-utils
.
最有用的是 matcherHint
、printExpected
和 printReceived
,可以很好地格式化错误消息。例如,看一下 toBe
匹配器的实现:
¥The most useful ones are matcherHint
, printExpected
and printReceived
to format the error messages nicely. For example, take a look at the implementation for the toBe
matcher:
const {diff} = require('jest-diff');
expect.extend({
toBe(received, expected) {
const options = {
comment: 'Object.is equality',
isNot: this.isNot,
promise: this.promise,
};
const pass = Object.is(received, expected);
const message = pass
? () =>
// eslint-disable-next-line prefer-template
this.utils.matcherHint('toBe', undefined, undefined, options) +
'\n\n' +
`Expected: not ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(received)}`
: () => {
const diffString = diff(expected, received, {
expand: this.expand,
});
return (
// eslint-disable-next-line prefer-template
this.utils.matcherHint('toBe', undefined, undefined, options) +
'\n\n' +
(diffString && diffString.includes('- Expect')
? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(received)}`)
);
};
return {actual: received, message, pass};
},
});
这将打印如下内容:
¥This will print something like this:
expect(received).toBe(expected)
Expected value to be (using Object.is):
"banana"
Received:
"apple"
当断言失败时,错误消息应向用户提供尽可能多的必要信号,以便他们能够快速解决问题。你应该制作精确的失败消息,以确保自定义断言的用户拥有良好的开发者体验。
¥When an assertion fails, the error message should give as much signal as necessary to the user so they can resolve their issue quickly. You should craft a precise failure message to make sure users of your custom assertions have a good developer experience.
this.customTesters
如果你的匹配器使用 this.equals
进行深度相等检查,你可能希望将用户提供的自定义测试器传递给 this.equals
。用户使用 addEqualityTesters
API 提供的自定义相等测试器可在此属性上使用。内置的 Jest 匹配器将 this.customTesters
(以及其他内置测试器)传递给 this.equals
以进行深度相等,并且你的自定义匹配器可能想要执行相同的操作。
¥If your matcher does a deep equality check using this.equals
, you may want to pass user-provided custom testers to this.equals
. The custom equality testers the user has provided using the addEqualityTesters
API are available on this property. The built-in Jest matchers pass this.customTesters
(along with other built-in testers) to this.equals
to do deep equality, and your custom matchers may want to do the same.
自定义快照匹配器
¥Custom snapshot matchers
要在自定义匹配器中使用快照测试,你可以导入 jest-snapshot
并在匹配器中使用它。
¥To use snapshot testing inside of your custom matcher you can import jest-snapshot
and use it from within your matcher.
这是一个快照匹配器,它修剪要存储的给定长度 .toMatchTrimmedSnapshot(length)
的字符串:
¥Here's a snapshot matcher that trims a string to store for a given length, .toMatchTrimmedSnapshot(length)
:
const {toMatchSnapshot} = require('jest-snapshot');
expect.extend({
toMatchTrimmedSnapshot(received, length) {
return toMatchSnapshot.call(
this,
received.slice(0, length),
'toMatchTrimmedSnapshot',
);
},
});
it('stores only 10 characters', () => {
expect('extra long string oh my gerd').toMatchTrimmedSnapshot(10);
});
/*
Stored snapshot will look like:
exports[`stores only 10 characters: toMatchTrimmedSnapshot 1`] = `"extra long"`;
*/
还可以为内联快照创建自定义匹配器,快照将正确添加到自定义匹配器中。但是,当第一个参数是属性匹配器时,内联快照将始终尝试附加到第一个参数或第二个参数,因此不可能在自定义匹配器中接受自定义参数。
¥It's also possible to create custom matchers for inline snapshots, the snapshots will be correctly added to the custom matchers. However, inline snapshot will always try to append to the first argument or the second when the first argument is the property matcher, so it's not possible to accept custom arguments in the custom matchers.
const {toMatchInlineSnapshot} = require('jest-snapshot');
expect.extend({
toMatchTrimmedInlineSnapshot(received, ...rest) {
return toMatchInlineSnapshot.call(this, received.slice(0, 10), ...rest);
},
});
it('stores only 10 characters', () => {
expect('extra long string oh my gerd').toMatchTrimmedInlineSnapshot();
/*
The snapshot will be added inline like
expect('extra long string oh my gerd').toMatchTrimmedInlineSnapshot(
`"extra long"`
);
*/
});
async
如果你的自定义内联快照匹配器是异步的,即使用 async
-await
,你可能会遇到类似 "不支持同一调用的多个内联快照" 的错误。Jest 需要额外的上下文信息来查找自定义内联快照匹配器用于正确更新快照的位置。
¥If your custom inline snapshot matcher is async i.e. uses async
-await
you might encounter an error like "Multiple inline snapshots for the same call are not supported". Jest needs additional context information to find where the custom inline snapshot matcher was used to update the snapshots properly.
const {toMatchInlineSnapshot} = require('jest-snapshot');
expect.extend({
async toMatchObservationInlineSnapshot(fn, ...rest) {
// The error (and its stacktrace) must be created before any `await`
this.error = new Error();
// The implementation of `observe` doesn't matter.
// It only matters that the custom snapshot matcher is async.
const observation = await observe(async () => {
await fn();
});
return toMatchInlineSnapshot.call(this, recording, ...rest);
},
});
it('observes something', async () => {
await expect(async () => {
return 'async action';
}).toMatchTrimmedInlineSnapshot();
/*
The snapshot will be added inline like
await expect(async () => {
return 'async action';
}).toMatchTrimmedInlineSnapshot(`"async action"`);
*/
});
帮助
¥Bail out
通常,jest
会尝试匹配测试中预期的每个快照。
¥Usually jest
tries to match every snapshot that is expected in a test.
有时,如果先前的快照失败,则继续测试可能没有意义。例如,当你在各种转换后制作状态机的快照时,一旦一个转换产生错误的状态,你就可以中止测试。
¥Sometimes it might not make sense to continue the test if a prior snapshot failed. For example, when you make snapshots of a state-machine after various transitions you can abort the test once one transition produced the wrong state.
在这种情况下,你可以实现一个自定义快照匹配器,该快照匹配器会抛出第一个不匹配的情况,而不是收集每个不匹配的情况。
¥In that case you can implement a custom snapshot matcher that throws on the first mismatch instead of collecting every mismatch.
const {toMatchInlineSnapshot} = require('jest-snapshot');
expect.extend({
toMatchStateInlineSnapshot(...args) {
this.dontThrow = () => {};
return toMatchInlineSnapshot.call(this, ...args);
},
});
let state = 'initial';
function transition() {
// Typo in the implementation should cause the test to fail
if (state === 'INITIAL') {
state = 'pending';
} else if (state === 'pending') {
state = 'done';
}
}
it('transitions as expected', () => {
expect(state).toMatchStateInlineSnapshot(`"initial"`);
transition();
// Already produces a mismatch. No point in continuing the test.
expect(state).toMatchStateInlineSnapshot(`"loading"`);
transition();
expect(state).toMatchStateInlineSnapshot(`"done"`);
});