An Async Example
首先, 像 Getting Started 里面所说的那样, 启用babel的支持
让我们实现一个从API获取用户信息并返回用户名的简单模块.
// user.js import request from './request'; export function getUserName(userID) { return request('/users/' + userID).then(user => user.name); }
在上面的实现中,我们希望request.js
模块会返回一个Promise对象.我们就可以用过链式调用 then
来接收用户名
想象一下 request.js
连接网络和获取用户数据将会是︰
// request.js const http = require('http'); export default function request(url) { return new Promise(resolve => { // 这是一个HTTP请求的例子, 用来从API获取用户信息 // 这个模块编写在 __mocks__/request.js http.get({path: url}, response => { let data = ''; response.on('data', _data => data += _data); response.on('end', () => resolve(data)); }); }); }
因为我们并不希望我们的测试连接网络,因此我们要在 __mocks__
文件夹中创建一个手动模拟我们的request.js
模块。 就像是这样:
// __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.', }) ); }); }
现在我们就来编写我们的异步函数的测试
// __tests__/user-test.js jest.mock('../request'); import * as user from '../user'; //断言必须返回一个primose it('works with promises', () => { expect.assertions(1); return user.getUserName(4).then(data => expect(data).toEqual('Mark')); });
我们调用 jest.mock('../request ')
告诉jest 使用我们手动的创建的模拟数据。 it
断言的是将会返回一个Promise对象. 你可以随时调用任意多个expect
, 只要你最后返回的是一个Promise
.resolves
#
仅用于jest 20.0.0+ #
通过 resolves
能更加简单地解析一个fulfilled 态的 Promise的返回值. 如果Promise是rejected态的话, 断言将会返回失败.
it('works with resolves', () => { expect.assertions(1); return expect(user.getUserName(5)).resolves.toEqual('Paul'); });
async
/await
#
在测试里面我们可以很简单地使用async
/await
, 编写和前面相同的例子:
// 使用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'); });
想要在你的项目中使用 async/await, 要先安装 babel-preset-env
并且在 .babelrc
中启用这个功能.
错误处理 #
可以使用 .catch
方法处理错误。 请确保添加 expect.assertions
来验证一定数量的断言被调用。 否则一个fulfilled态的Promise 不会让测试失败︰
//用 Promise.catch 测试一个异步的错误 test('tests error with promises', async () => { expect.assertions(1); return user.getUserName(2).catch(e => expect(e).toEqual({ error: 'User with 2 not found.', }) ); }); // 或者使用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
#
仅用于jest 20.0.0+ #
.rejects
功能和 .resolves
基本一致.如果 promise 处于 fulfilled 态, 测试会自动报错.
// 用`.rejects`.来测试一个异步的错误 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.
如果你想要测试定时器,比如 setTimeout
可以去查看 Timer mocks 的文档。