Expect
テストを作成する時に、値が特定の条件に合致することを確認する必要がよくあるでしょう。 expect
によって様々な事柄を検証するための数多くの「マッチャ」を利用することができます。
For additional Jest matchers maintained by the Jest Community check out jest-extended
.
このページの TypeScript の例は、次のように Jest の API を明示的にインポートした場合にのみ動作します。
import {expect, jest, test} from '@jest/globals';
TypeScript で Jest をセットアップする方法の詳細については、Getting Started ガイドを参照してください。
リファレンス
- Expect
- 修飾子
- Matchers
.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)
- Asymmetric Matchers
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)
- Assertion Count
- Extend Utilities
- Serializable properties
Expect
expect(value)
expect
は値をテストしたい時に毎回使用する関数です。 expect
のみを呼び出すということはほとんどありません。 代わりに、 値について何らかの事をアサートする"マッチャ"関数とともにexpect
を使用することでしょう。
この事は例を見れば簡単に理解できます。 'grapefruit'
という文字列を返すはずのbestLaCroixFlavor()
メソッドがあるとしましょう。 以下のようにテストするでしょう:
test('the best flavor is grapefruit', () => {
expect(bestLaCroixFlavor()).toBe('grapefruit');
});
このケースでは、 toBe
がマッチャ関数です。 様々な事をテストするのを手助けする数多くの異なるマッチャ関数があり、以下にまとめられています。
expect
への引数はコードが生成する値であるべきであり、いかなるマッチャへの引数は正解の値であるべきです。 それらを混同して使用すれば、テストは動作するものの、失敗したテストから出力されるエラーメッセージはおかしなものになります。
修飾子
.not
何かをテストする方法が分かっているなら、 .not
によってその反対の事をテストできます。 例えば以下のコードでは、ラクロワ飲料で一番美味しいのはココナッツ味ではないことをテストでします。
test('the best flavor is not coconut', () => {
expect(bestLaCroixFlavor()).not.toBe('coconut');
});
.resolves
追加のマッチャをチェーンするためにに完了したpromiseの値を取り出すにはresolves
を使用して下さい。 promiseがrejectされた場合はアサーションは失敗します。
例えば、以下のコードではpromiseが完了した結果の値が'lemon'
であることをテストします:
test('resolves to lemon', () => {
// make sure to add a return statement
return expect(Promise.resolve('lemon')).resolves.toBe('lemon');
});
Promise をテストしているため、テストはまだ非同期です。 このために、ラップされていないアサーションを返すことで、Jest に処理が完了するまで待つように伝える必要があるのです。
また、async/await
を.resolves
と組み合わせて使うことができます。
test('resolves to lemon', async () => {
await expect(Promise.resolve('lemon')).resolves.toBe('lemon');
await expect(Promise.resolve('lemon')).resolves.not.toBe('octopus');
});
.rejects
追加のマッチャをチェーンするためににrejectされたpromiseの理由を取り出すには .rejects
を使用して下さい。 promiseが完了した場合はアサーションは失敗します。
たとえば、このコードは Promise が 'octopus'
という理由で reject されたことをテストします。
test('rejects to octopus', () => {
// make sure to add a return statement
return expect(Promise.reject(new Error('octopus'))).rejects.toThrow(
'octopus',
);
});
Promise をテストしているため、テストはまだ非同期です。 このために、ラップされていないアサーションを返すことで、Jest に処理が完了するまで待つように伝える必要があるのです。
また、async/await
を.rejects
と組み合わせて使うことができます。
test('rejects to octopus', async () => {
await expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus');
});
Matchers
.toBe(value)
プリミティブ値を比較したり、オブジェクトインスタンスの参照IDを確認したりするには、 .toBe
を使用します。 It calls Object.is
to compare values, which is even better for testing than ===
strict equality operator.
例えば以下のコードでは can
オブジェクトのいくつかのプロパティを検証します。
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
を使用してください。
.toBe
マッチャー は 参照IDをチェックしますが、アサーションが失敗した場合、 値の再帰的な比較を** 報告します**。 特にレポートが大きい場合には、プロパティ間の差分は、テストが失敗する理原因を解明することに寄与しません。 そうすると、比較処理を expect
関数の中に移すことでしょう 例えば、要素が同じインスタンスであるかどうかをアサートするには、次のようにします。
- rewrite
expect(received).toBe(expected)
asexpect(Object.is(received, expected)).toBe(true)
- rewrite
expect(received).not.toBe(expected)
asexpect(Object.is(received, expected)).toBe(false)
.toHaveBeenCalled()
Use .toHaveBeenCalled
to ensure that a mock function was called.
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. このテストスイートでテストすることができます:
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)
モック関数が期待した回数だけ呼ばれたことを確認するには.toHaveBeenCalledTimes
を使用して下さい。
例えばdrink
関数を引数に取って渡された飲み物の配列に適用する drinkEach(drink, Array<flavor>)
関数があるとしましょう。 drink関数が正しい回数だけ呼ばれたことを確認したいでしょう。 このテストスイートでテストすることができます:
test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenCalledTimes(2);
});
.toHaveBeenCalledWith(arg1, arg2, ...)
モック関数が特定の引数を与えられて呼び出されたことを確認するには .toHaveBeenCalledWith
を使用して下さい。 The arguments are checked with the same algorithm that .toEqual
uses.
例えば register
関数で飲み物を登録でき、applyToAll(f)
は 関数f
を全ての登録された飲み物に適用するものとしましょう。 この振る舞いを確認するコードは、下記のように書けるでしょう:
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, ...)
モック関数がある場合は .toHaveBeenLastCalledWith
を使用して、最後の呼び出しがどんな引数を渡されたかをテストすることができます。 例えば 複数の風味に対して関数f
を適用するapplyToAllFlavors(f)
関数があり、関数fが最後に操作した風味が'mango'
だったとしましょう。 以下のようにテストコードを書くことができます。
test('applying to all flavors does mango last', () => {
const drink = jest.fn();
applyToAllFlavors(drink);
expect(drink).toHaveBeenLastCalledWith('mango');
});
.toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....)
あるモック関数があるとき、.toHaveReturned
を使用すると、モック関数が正しく (つまり、例外が発生せずに) 変えることをテストできます。 たとえば、true
を返すモック関数 drink
があるとすると、テストは次のように書くことができます。 以下のようにテストコードを書くことができます。
test('drink は n 回目の呼び出しで期待した値を返す', () => {
const beverage1 = {name: 'La Croix (レモン)'};
const beverage2 = {name: 'La Croix (オレンジ)'};
const drink = jest.fn(beverage => beverage.name);
drink(beverage1);
drink(beverage2);
expect(drink).toHaveNthReturnedWith(1, 'La Croix (レモン)');
expect(drink).toHaveNthReturnedWith(2, 'La Croix (オレンジ)');
});
The nth argument must be positive integer starting from 1.
.toHaveReturned()
あるモック関数があるとき、.toHaveReturned
を使用すると、モック関数が正しく (つまり、例外が発生せずに) 変えることをテストできます。 たとえば、true
を返すモック関数 drink
があるとすると、テストは次のように書くことができます。 以下のようにテストコードを書くことができます。
test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['レモン', 'タコ']);
expect(drink).toHaveBeenNthCalledWith(1, 'レモン');
expect(drink).toHaveBeenNthCalledWith(2, 'タコ');
});
.toHaveReturnedTimes(number)
モック関数がちょうど指定した回数だけ正しく (つまり、例外が発生せずに) 返ったことを確認するには、.toHaveReturnedTimes
を使用してください。 例外が発生したモック関数の呼び出しは、関数の返した回数としてカウントされません。
たとえば、true
を返すモック関数 drink
があるとすると、テストは次のように書くことができます。 以下のようにテストコードを書くことができます。
test('drinks は return する', () => {
const drink = jest.fn(() => true);
drink();
expect(drink).toHaveReturned();
});
.toHaveReturnedWith(value)
モック関数が特定の値を返すことを確認するには、. toHaveReturnedWith
を使用してください。
たとえば、飲まれた飲み物 (beverage) の名前を返すモック関数 drink
があるとすると、テストは次のように書くことができます。 以下のようにテストコードを書くことができます。
test('drink は2回正しく return する', () => {
const drink = jest.fn(() => true);
drink();
drink();
expect(drink).toHaveReturnedTimes(2);
});
.toHaveLastReturnedWith(value)
モック関数が最後に返した値が特定の値であるかどうかをテストするには、.toHaveLastReturnedWith
を使用してください。 モック関数の最後の呼び出しで例外が発生した場合、期待した値としてどんな値を指定したとしても、このマッチャは無条件に失敗します。
たとえば、飲まれた飲み物 (beverage) の名前を返すモック関数 drink
があるとすると、テストは次のように書くことができます。 以下のようにテストコードを書くことができます。
test('drink は La Croix を返す', () => {
const beverage = {name: 'La Croix'};
const drink = jest.fn(beverage => beverage.name);
drink(beverage);
expect(drink).toHaveReturnedWith('La Croix');
});
.toHaveNthReturnedWith(nthCall, value)
モック関数が n 回目に返した値が特定の値であるかどうかをテストするには、.toHaveNthReturnedWith
を使用してください。 モック関数の n 回目の呼び出しで例外が発生した場合、期待した値としてどんな値を指定したとしても、このマッチャは無条件に失敗します。
たとえば、飲まれた飲み物 (beverage) の名前を返すモック関数 drink
があるとすると、テストは次のように書くことができます。 以下のようにテストコードを書くことができます。
test('drink は最後に La Croix (Orange) を return する', () => {
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)');
});
The nth argument must be positive integer starting from 1.
.toHaveLength(number)
オブジェクトが.length
プロパティを持ち、特定の数値であるかを確認するには、.toHaveLength
を使用して下さい。
配列や文字列のサイズを確認するのに特に便利です。
expect([1, 2, 3]).toHaveLength(3);
expect('abc').toHaveLength(3);
expect('').not.toHaveLength(5);
.toHaveProperty(keyPath, value?)
オブジェクトの指定された参照keyPath
のプロパティが存在するかを確認するには、.toHaveProperty
を使用して下さい。 オブジェクト内で深くネストされたプロパティをチェックするには、 深い階層を参照するために、 ドット表記や keyPath を含む配列を使用することができます。
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
を利用しています。
// 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
では、浮動小数点数を近似的な等価性で評価します。
オプションのnumDigits
引数は小数点以下の桁数の上限を設定します。 デフォルト値 2
の場合、テスト条件は Math.abs(expected - received) < 0.005
以内 (つまり、 10 ** -2 / 2
)となります。
なぜなら、10 進数(ベース 10)での計算は、限られた精度の二進数(ベース 2)での表現による丸め誤差を含んでいることがよくあるからdす。 例えば、このテストは失敗します:
test('adding works sanely with decimals', () => {
expect(0.2 + 0.1).toBe(0.3); // Fails!
});
JavaScriptでは0.2 + 0.1
は実際には 0.30000000000000004
なのでこのテストは失敗します。
例えば、このテストは小数点以下5桁の精度で合格します。
test('adding works sanely with decimals', () => {
expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
});
toBeCloseTo
が解決すべきなのは浮動小数点におけるエラーなので、大きな整数値はサポートされていません。
.toBeDefined()
変数が undefined ではないことを検証するには、.toBeDefined
を使用します。 例えば、fetchNewFlavorIdea()
関数が 何らかの値 を返すことを検証するには、以下のように記述します:
test('there is a new flavor idea', () => {
expect(fetchNewFlavorIdea()).toBeDefined();
});
expect(fetchNewFlavorIdea()).not.toBe(undefined)
とも書くことができますが、undefined
を直接コード内で参照するのは避けたほうが実務上良いでしょう。
.toBeFalsy()
値がどのようなものかを気にせず、真偽値のコンテクストの中で値が偽であることを確認したい場合は.toBeFalsy
を使用して下さい。 例えば、以下のようなアプリケーションコードがあったとします:
drinkSomeLaCroix();
if (!getErrors()) {
drinkMoreLaCroix();
}
getErrors
がどんなものを返すかは特に気にしないでしょう - false
、null
、あるいは 0
を返すかもしれませんが、それでもコードは動作します。 だからラクロワ飲料を飲んだ後でエラーが無いことをテストしたければ、このように書くことができます:
test('drinking La Croix does not lead to errors', () => {
drinkSomeLaCroix();
expect(getErrors()).toBeFalsy();
});
JavaScriptでは、偽と類推される6つの値があります: false
、 0
、 ''
、 null
、 undefined
、 そして NaN
です。 他の全ては真と類推されます。
.toBeGreaterThan(number | bigint)
toBeGreaterThan
により、 実際値 > 期待値
の条件でnumber型またはbigint 型の数値を比較します。 例えば、 ouncesPerCan()
が 10 オンスより大きい値を返すことをテストします。
test('ounces per can is more than 10', () => {
expect(ouncesPerCan()).toBeGreaterThan(10);
});
.toBeGreaterThanOrEqual(number | bigint)
toBeGreaterThanOrEqual
を使用して、 実際値 >= 期待値
の条件でnumber型またはbigint 型の数値を比較します。 例えば、 ouncesPerCan()
が12 オンス以上の値を返すことをテストします。
test('ounces per can is at least 12', () => {
expect(ouncesPerCan()).toBeGreaterThanOrEqual(12);
});
.toBeLessThan(number | bigint)
toBeLessThan
を使用して、実際値 < 期待値
の条件でnumber型またはbigint 型の数値を比較します。 例えば、 ouncesPerCan()
が 20 オンス未満の値を返すことをテストします。
test('ounces per can is less than 20', () => {
expect(ouncesPerCan()).toBeLessThan(20);
});
.toBeLessThanOrEqual(number | bigint)
toBeLessThanOrEqual
を使用して、 実際値 <= 期待値
の条件でnumber型またはbigint 型の数値を比較します。 例えば、 ouncesPerCan()
が12 オンス以下の値を返すことをテストします。
test('ounces per can is at most 12', () => {
expect(ouncesPerCan()).toBeLessThanOrEqual(12);
});
.toBeInstanceOf(Class)
オブジェクトがクラスのインスタンスであることを確認するには .toBeInstanceOf(Class)
を使用して下さい。 このマッチャは instanceof
を内部で利用しています。
class A {}
expect(new A()).toBeInstanceOf(A);
expect(() => {}).toBeInstanceOf(Function);
expect(new A()).toBeInstanceOf(Function); // throws
.toBeNull()
.toBeNull()
は .toBe(null)
と同じですが、エラーメッセージが少し分かりやすいものになっています。 そのため何かがnullであることを確認したい場合は .toBeNull()
を使用して下さい。
function bloop() {
return null;
}
test('bloop returns null', () => {
expect(bloop()).toBeNull();
});