当前位置: 首页 > 文档资料 > Jest 中文文档 >

An Async Example

优质
小牛编辑
133浏览
2023-12-01

首先, 像 Getting Started 里面所说的那样, 启用babel的支持

Let's implement a module that fetches user data from an API and returns the user name.

// user.js
import request from './request';

export function getUserName(userID) {
  return request('/users/' + userID).then(user => user.name);
}

In the above implementation we expect the request.js module to return a promise. We chain a call to then to receive the user name.

Now imagine an implementation of request.js that goes to the network and fetches some user data:

// request.js
const http = require('http');

export default function request(url) {
  return new Promise(resolve => {
    // 这是一个HTTP请求的例子, 用来从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));
    });
  });
}

Because we don't want to go to the network in our test, we are going to create a manual mock for our request.js module in the __mocks__ folder (the folder is case-sensitive, __MOCKS__ will not work). 就像是这样:

// __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对象. You can chain as many Promises as you like and call expect at any time, as long as you return a Promise at the end.

.resolves

There is a less verbose way using resolves to unwrap the value of a fulfilled promise together with any other matcher. If the promise is rejected, the assertion will fail.

it('works with resolves', () => {
  expect.assertions(1);
  return expect(user.getUserName(5)).resolves.toEqual('Paul');
});

async/await

Writing tests using the async/await syntax is also possible. Here is how you'd write the same examples from before:

// 使用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');
});

To enable async/await in your project, install @babel/preset-env and enable the feature in your babel.config.js file.

错误处理

可以使用 .catch 方法处理错误。 请确保添加 expect.assertions 来验证一定数量的断言被调用。 否则一个fulfilled态的Promise 不会让测试失败︰

//用 Promise.catch 测试一个异步的错误
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

The.rejects helper works like the .resolves helper. 如果 Promise 被拒绝,则测试将自动失败。 expect.assertions(number) is not required but recommended to verify that a certain number of assertions are called during a test. It is otherwise easy to forget to return/await the .resolves assertions.

// 用`.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.',
  });
});

The code for this example is available at examples/async.

If you'd like to test timers, like setTimeout, take a look at the Timer mocks documentation.