Jestテスト構文シリーズのExpect
17087 ワード
Methods
Expectは主に検証操作を実現するために使用され、JestのExpectは以下の検証方法を提供する.
Reference
expect(value)
値をテストするたびにexpect関数を使用すると、expect自体を呼び出すことはめったにありません.逆に、expect関数とmatcher関数を使用して値の一部を断言します.理解を容易にするために、ここでは、expectが結果を返すことを期待する方法bestLaCroixFlavor()があると仮定します.test('the best flavor is grapefruit', () => {
expect(bestLaCroixFlavor()).toBe('grapefruit');
});
上記の例では、toBeはmatcher関数であり、異なる内容をテストするのに役立つために、Jestは多くの異なるmatcher関数を提供しています.expectのパラメータはコード生成の値であり、マッチングプログラムの任意のパラメータは正しい値であるべきである.
expect.extend(matchers)
expectを使ってもいいです.extendは自分のmatcherをJestに追加します.たとえば、theory libraryをテストしていて、数字が他の数で割り切れるとよく断言している場合は、toBeDivisibleBy matcherとして抽象化することができます.expect.extend({
toBeDivisibleBy(received, argument) {
const pass = received % argument == 0;
if (pass) {
return {
message: () =>
`expected ${received} not to be divisible by ${argument}`,
pass: true,
};
} else {
return {
message: () => `expected ${received} to be divisible by ${argument}`,
pass: false,
};
}
},
});
test('even and odd numbers', () => {
expect(100).toBeDivisibleBy(2);
expect(101).not.toBeDivisibleBy(2);
expect({apples: 6, bananas: 3}).toEqual({
apples: expect.toBeDivisibleBy(2),
bananas: expect.not.toBeDivisibleBy(2),
});
});
expect.extendsはまた非同期マッチングをサポートし、非同期マッチングはpromiseを返すので、返される値を待つ必要があります.例matcherを使用して、それらの使い方を説明します.toBeDivisibleByではなく、非常に似たようなmatcherを実現するには、分割可能な数字が外部ソースから抽出されるのが唯一の違いです.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();
});
マッチング器は、2つのキーを持つオブジェクト(またはオブジェクトのpromise)を返す必要があります.passは一致があるかどうかを示し、messageはパラメータのない関数を提供し、失敗したときにエラーメッセージを返します.したがってpassがfalseである場合、expect(x)となる.yourmatcher()が失敗した場合、メッセージはエラーメッセージを返すべきです.passがtrueである場合、メッセージはexpect(x)を返すべきである.no . yourmatcher()が失敗したときのエラーメッセージ.
this.equals(a, b)
2つのオブジェクトが同じ値(再帰的に)を持つ場合、trueが返されます.this.utilsには多くの有用なツールがあり、utilsは主にjest-matcher-utilsからのエクスポートから構成されています.最も有用なのはmatcherHint、printExpected、printReceivedであり、エラーメッセージをうまくフォーマットできます.const diff = require('jest-diff');
expect.extend({
toBe(received, expected) {
const pass = Object.is(received, expected);
const message = pass
? () =>
this.utils.matcherHint('.not.toBe') +
'
' +
`Expected value to not be (using Object.is):
` +
` ${this.utils.printExpected(expected)}
` +
`Received:
` +
` ${this.utils.printReceived(received)}`
: () => {
const diffString = diff(expected, received, {
expand: this.expand,
});
return (
this.utils.matcherHint('.toBe') +
'
' +
`Expected value to be (using Object.is):
` +
` ${this.utils.printExpected(expected)}
` +
`Received:
` +
` ${this.utils.printReceived(received)}` +
(diffString ? `
Difference:
${diffString}` : '')
);
};
return {actual: received, message, pass};
},
});
上記のコードを実行すると、次のエラーメッセージが表示されます.expect(received).toBe(expected)
Expected value to be (using Object.is):
"banana"
Received:
"apple"
断言に失敗した場合、エラーメッセージは、ユーザが迅速に問題を解決できるように、ユーザに必要なできるだけ多くの信号を提供するべきである.したがって、カスタムブレークスルーのユーザーが良好な開発経験を持っていることを確認するために、正確な失敗メッセージを作成する必要があります.
expect.anything()
nullまたはundefined以外のコンテンツに一致します.文字値ではなくtoEqualまたはtoBeCalledWithを内部で使用できます.たとえば、シミュレーション関数が呼び出されているかどうかを確認したい場合は、そのパラメータは空ではありません.test('map calls its argument with a non-null argument', () => {
const mock = jest.fn();
[1].map(x => mock(x));
expect(mock).toBeCalledWith(expect.anything());
});
expect.any(constructor)
指定したコンストラクション関数によって作成された内容を一致させます.文字値ではなくtoEqualまたはtoBeCalledWithを内部で使用できます.たとえば、シミュレーション関数が呼び出されたときに数値があるかどうかを確認したい場合.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).toBeCalledWith(expect.any(Number));
});
expect.arrayContaining(array)
受信された配列に一致します.この配列は、予想された配列のすべての要素、すなわち、予想された配列が受信された配列のサブセットであるため、予想された配列に属さない要素を含む受信された配列に一致します.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.assertions(number)
テスト中に一定数のブレークスルーが呼び出されたことを確認します.これは、コールバック中のブレークスルーが確実に呼び出されることを保証するために、非同期コードをテストする際に通常役立ちます.2つのコールバックcallback 1とcallback 2を受信する関数doAsyncがあるとします.これは、未知の順序で非同期的に呼び出されます.test('doAsync calls both callbacks', () => {
expect.assertions(2);
function callback1(data) {
expect(data).toBeTruthy();
}
function callback2(data) {
expect(data).toBeTruthy();
}
doAsync(callback1, callback2);
});
expect.hasAssertions()
テスト中に少なくとも1つの断言が呼び出されたことを確認します.非同期コードをテストする場合、これは通常、コールバック中の断言が確実に呼び出されることを保証するために役立ちます.
ステータスを処理する関数がいくつかあると仮定すると、prepareStateはステータスオブジェクトのコールバックを呼び出し、validateStateはそのステータスオブジェクト上で実行され、waitOnStateはすべてのprepareStateコールバックが完了するまで承諾を返します.test('prepareState prepares a valid state', () => {
expect.hasAssertions();
prepareState(state => {
expect(validateState(state)).toBeTruthy();
});
return waitOnState();
});
expect.not.arrayContaining(array)
受信した配列を一致させます.この配列には、予想される配列の要素が含まれません.すなわち、所望の配列は受信配列のサブセットではなく、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.not.objectContaining(object)
予期した属性に再帰的に一致しない受信オブジェクトを一致させます.すなわち、所望のオブジェクトは受信オブジェクトのサブセットではない.したがって、受信したオブジェクトと一致し、そのオブジェクトには予期しないプロパティが含まれます.expectとobjectcontainsは逆です.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.not.stringContaining(string)
マッチングは、expectと正確に所望の文字列を含まない受信文字列である.stringContaining.反対です.describe('not.stringContaining', () => {
const expected = 'Hello world!';
it('matches if the actual string does not contain the expected substring', () => {
expect('How are you?').toEqual(expect.not.stringContaining(expected));
});
});
expect.not.stringMatching(string | regexp)
予想regexpに一致しない受信文字列をexpectと一致する.stringMatching.反対です.describe('not.stringMatching', () => {
const expected = /Hello world!/;
it('matches if the actual string does not match the expected regex', () => {
expect('How are you?').toEqual(expect.not.stringMatching(expected));
});
});
expect.objectContaining(object)
一致は、所望の属性の任意の受信オブジェクトに再帰的に一致する.すなわち、所望のオブジェクトは、受信オブジェクトのサブセットである.したがって、受信したオブジェクトと一致し、そのオブジェクトには予期しないプロパティが含まれます.
所望のオブジェクトの文字属性値とは異なり、matchers、expectを使用できます.anything()など.イベントオブジェクトを使用してonPress関数を呼び出す場合、イベントにeventがあるかどうかを検証する必要があります.x属性とy属性.test('onPress gets called with the right thing', () => {
const onPress = jest.fn();
simulatePresses(onPress);
expect(onPress).toBeCalledWith(
expect.objectContaining({
x: expect.any(Number),
y: expect.any(Number),
}),
);
});
expect.stringMatching(string | regexp)
予想regexpと一致する受信文字列を一致させ、文字の値の代わりに使用できます.
test('the best flavor is grapefruit', () => {
expect(bestLaCroixFlavor()).toBe('grapefruit');
});
expect.extend({
toBeDivisibleBy(received, argument) {
const pass = received % argument == 0;
if (pass) {
return {
message: () =>
`expected ${received} not to be divisible by ${argument}`,
pass: true,
};
} else {
return {
message: () => `expected ${received} to be divisible by ${argument}`,
pass: false,
};
}
},
});
test('even and odd numbers', () => {
expect(100).toBeDivisibleBy(2);
expect(101).not.toBeDivisibleBy(2);
expect({apples: 6, bananas: 3}).toEqual({
apples: expect.toBeDivisibleBy(2),
bananas: expect.not.toBeDivisibleBy(2),
});
});
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();
});
const diff = require('jest-diff');
expect.extend({
toBe(received, expected) {
const pass = Object.is(received, expected);
const message = pass
? () =>
this.utils.matcherHint('.not.toBe') +
'
' +
`Expected value to not be (using Object.is):
` +
` ${this.utils.printExpected(expected)}
` +
`Received:
` +
` ${this.utils.printReceived(received)}`
: () => {
const diffString = diff(expected, received, {
expand: this.expand,
});
return (
this.utils.matcherHint('.toBe') +
'
' +
`Expected value to be (using Object.is):
` +
` ${this.utils.printExpected(expected)}
` +
`Received:
` +
` ${this.utils.printReceived(received)}` +
(diffString ? `
Difference:
${diffString}` : '')
);
};
return {actual: received, message, pass};
},
});
expect(received).toBe(expected)
Expected value to be (using Object.is):
"banana"
Received:
"apple"
test('map calls its argument with a non-null argument', () => {
const mock = jest.fn();
[1].map(x => mock(x));
expect(mock).toBeCalledWith(expect.anything());
});
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).toBeCalledWith(expect.any(Number));
});
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),
);
});
});
test('doAsync calls both callbacks', () => {
expect.assertions(2);
function callback1(data) {
expect(data).toBeTruthy();
}
function callback2(data) {
expect(data).toBeTruthy();
}
doAsync(callback1, callback2);
});
test('prepareState prepares a valid state', () => {
expect.hasAssertions();
prepareState(state => {
expect(validateState(state)).toBeTruthy();
});
return waitOnState();
});
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),
);
});
});
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));
});
});
describe('not.stringContaining', () => {
const expected = 'Hello world!';
it('matches if the actual string does not contain the expected substring', () => {
expect('How are you?').toEqual(expect.not.stringContaining(expected));
});
});
describe('not.stringMatching', () => {
const expected = /Hello world!/;
it('matches if the actual string does not match the expected regex', () => {
expect('How are you?').toEqual(expect.not.stringMatching(expected));
});
});
test('onPress gets called with the right thing', () => {
const onPress = jest.fn();
simulatePresses(onPress);
expect(onPress).toBeCalledWith(
expect.objectContaining({
x: expect.any(Number),
y: expect.any(Number),
}),
);
});
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),
);
});
});
.toBe(value)
toBeは、1つの値があなたの期待に合っているかどうかを確認するだけです.オブジェクトを使用している場合は、完全に等しいことを確認します.
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)
2つのオブジェクトに同じ値があるかどうかを確認するには、を使用します.toequal.このmatcherは、オブジェクトIDをチェックするのではなく、すべてのフィールドの等化を再帰的にチェックします.これは「深さ等化」とも呼ばれます.例えば、toEqualとtoBeはこのテストキットで異なるので、すべてのテストに合格します.
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);
});
});
.toMatchObject(object)
使用するtomatchobject JavaScriptオブジェクトがオブジェクトの属性サブセットに一致するかどうかを確認します.受信したオブジェクトと、予期しないオブジェクトにないプロパティが一致します.
また、オブジェクト配列を渡すこともできます.この方法は、受信した配列の各オブジェクト(上記のトマトオブジェクトの意味)が予想される配列の対応するオブジェクトと一致している場合にのみtrueを返します.2つの配列がarrayincludeではなく要素数で一致しているかどうかを確認するには、受信した配列に追加の要素を追加できるため、非常に役立ちます.
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 arrays', () => {
test('the number of elements must match exactly', () => {
expect([{foo: 'bar'}, {baz: 1}]).toMatchObject([{foo: 'bar'}, {baz: 1}]);
});
// .arrayContaining "matches a received array which contains elements that
// are *not* in the expected array"
test('.toMatchObject does not allow extra elements', () => {
expect([{foo: 'bar'}, {baz: 1}]).toMatchObject([{foo: 'bar'}]);
});
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},
]);
});
});
.toHaveProperty(keyPath ,value)
使用するtohavepropertyは、指定した参照keyPathにオブジェクトのプロパティがあるかどうかを確認します.オブジェクト内の深度ネストのプロパティを確認するには、ポイント表現または深度参照を含むkeyPathの配列を使用します.
オプションとして、ターゲットオブジェクトのkeyPathの値と等しいかどうかを確認する値を指定できます.このmatcherでは、toEqual()などの「深さが等しい」を使用し、すべてのフィールドの等しい性を再帰的にチェックします.
次の例では、ネストされたプロパティを持つhouseForSaleオブジェクトを示します.tohaveプロパティを使用して、オブジェクト内のさまざまなプロパティの存在と値を確認します.
const houseForSale = {
bath: true,
bedrooms: 4,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
area: 20,
wallColor: 'white',
'nice.oven': true,
},
};
test('this house has my desired features', () => {
// Simple Referencing
expect(houseForSale).toHaveProperty('bath');
expect(houseForSale).toHaveProperty('bedrooms', 4);
expect(houseForSale).not.toHaveProperty('pool');
// Deep referencing using dot notation
expect(houseForSale).toHaveProperty('kitchen.area', 20);
expect(houseForSale).toHaveProperty('kitchen.amenities', [
'oven',
'stove',
'washer',
]);
expect(houseForSale).not.toHaveProperty('kitchen.open');
// Deep referencing using an array containing the keyPath
expect(houseForSale).toHaveProperty(['kitchen', 'area'], 20);
expect(houseForSale).toHaveProperty(
['kitchen', 'amenities'],
['oven', 'stove', 'washer'],
);
expect(houseForSale).toHaveProperty(['kitchen', 'amenities', 0], 'oven');
expect(houseForSale).toHaveProperty(['kitchen', 'nice.oven']);
expect(houseForSale).not.toHaveProperty(['kitchen', 'open']);
});
その他:フロントエンドユニット試験のJest React試験フレームワークのenzyme Jest試験文法シリーズのGlobals Jest試験文法シリーズのMatchers