首先, 像Jest 從安裝開始里面所說的那樣, 啟用babel的支持
讓我們實(shí)現(xiàn)一個(gè)從 API 獲取用戶數(shù)據(jù)并返回用戶名的模塊。
// user.js
import request from './request';
export function getUserName(userID) {
return request('/users/' + userID).then(user => user.name);
}
在上面的實(shí)現(xiàn)中,我們期望?request.js
?模塊返回一個(gè) promise。我們鏈接一個(gè)調(diào)用來?then
?接收用戶名。
現(xiàn)在想象一個(gè)?request.js
?進(jìn)入網(wǎng)絡(luò)并獲取一些用戶數(shù)據(jù)的實(shí)現(xiàn):
// request.js
const http = require('http');
export default function request(url) {
return new Promise(resolve => {
// 這是一個(gè)HTTP請(qǐng)求的例子, 用來從API獲取用戶信息
// This module is being mocked in __mocks__/request.js
http.get({path: url}, response => {
let data = '';
response.on('data', _data => (data += _data));
response.on('end', () => resolve(data));
});
});
}
因?yàn)槲覀冊(cè)跍y(cè)試中不想去網(wǎng)絡(luò),所以我們將?request.js
?在?__mocks__
?文件夾中為我們的模塊創(chuàng)建一個(gè)手動(dòng)模擬(文件夾區(qū)分大小寫,?__MOCKS__
?將不起作用)。就像是這樣:
// __mocks__/request.js
const users = {
4: {name: 'Mark'},
5: {name: 'Paul'},
};
export default function request(url) {
return new Promise((resolve, reject) => {
const userID = parseInt(url.substr('/users/'.length), 10);
process.nextTick(() =>
users[userID]
? resolve(users[userID])
: reject({
error: 'User with ' + userID + ' not found.',
}),
);
});
}
現(xiàn)在我們就來編寫我們的異步函數(shù)的測(cè)試
// __tests__/user-test.js
jest.mock('../request');
import * as user from '../user';
//斷言必須返回一個(gè)primose
it('works with promises', () => {
expect.assertions(1);
return user.getUserName(4).then(data => expect(data).toEqual('Mark'));
});
我們調(diào)用 ?jest.mock('../request ')
? 告訴jest 使用我們手動(dòng)的創(chuàng)建的模擬數(shù)據(jù)。 ?it
?斷言的是將會(huì)返回一個(gè)Promise對(duì)象,你可以在任何時(shí)候給?expect
?打電話,只要你在最后回復(fù)一個(gè)承諾。
有一種不那么冗長(zhǎng)的方法?resolves
?用于將已履行的 Promise 的值與任何其他匹配器一起解包。如果 Promise 被拒絕,則斷言將失敗。
it('works with resolves', () => {
expect.assertions(1);
return expect(user.getUserName(5)).resolves.toEqual('Paul');
});
也可以使用?async
?/?await
?語法編寫測(cè)試。以下是如何編寫與之前相同的示例:
// 使用async/await
it('works with async/await', async () => {
expect.assertions(1);
const data = await user.getUserName(4);
expect(data).toEqual('Mark');
});
// async/await 也可以和 `.resolves` 一起使用.
it('works with async/await and resolves', async () => {
expect.assertions(1);
await expect(user.getUserName(5)).resolves.toEqual('Paul');
});
要在項(xiàng)目中啟用 ?async
?/?await
?,請(qǐng)?jiān)谀愕?babel.config.js
?文件中安裝并啟用@babel/preset-env功能。
可以使用? .catch
? 方法處理錯(cuò)誤。 請(qǐng)確保添加 ?expect.assertions
? 來驗(yàn)證一定數(shù)量的斷言被調(diào)用。 否則一個(gè)fulfilled態(tài)的Promise 不會(huì)讓測(cè)試失敗︰
//用 Promise.catch 測(cè)試一個(gè)異步的錯(cuò)誤
it('tests error with promises', () => {
expect.assertions(1);
return user.getUserName(2).catch(e =>
expect(e).toEqual({
error: 'User with 2 not found.',
}),
);
});
// Or using async/await.
it('tests error with async/await', async () => {
expect.assertions(1);
try {
await user.getUserName(1);
} catch (e) {
expect(e).toEqual({
error: 'User with 1 not found.',
});
}
});
該?.rejects
?助手的工作方式類似于?.resolves
?幫手。如果 Promise 被拒絕,則測(cè)試將自動(dòng)失敗。?expect.assertions(number)
?不是必需的,但建議驗(yàn)證在測(cè)試期間調(diào)用了一定數(shù)量的assertions。其實(shí)不然容易忘記?return
?/?await
?的?.resolves
? ?assertions
?。
// 用`.rejects`.來測(cè)試一個(gè)異步的錯(cuò)誤
it('tests error with rejects', () => {
expect.assertions(1);
return expect(user.getUserName(3)).rejects.toEqual({
error: 'User with 3 not found.',
});
});
// 或者與async/await 一起使用 `.rejects`.
it('tests error with async/await and rejects', async () => {
expect.assertions(1);
await expect(user.getUserName(3)).rejects.toEqual({
error: 'User with 3 not found.',
});
});
此示例的代碼位于examples/async。
如果想測(cè)試計(jì)時(shí)器,例如setTimeout,請(qǐng)查看計(jì)時(shí)器模擬文檔。
更多建議: