美文网首页
Jest - 异步例子

Jest - 异步例子

作者: 小黄人get徐先生 | 来源:发表于2019-08-22 20:23 被阅读0次

    首先,按照入门指南中的文档,在 Jest 中启用 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 => {
        // This is an example of an http request, for example to fetch
        // user data from an 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));
        });
      });
    }
    

    因为我们不想在测试中进入网络,所以我们将在_mocks__文件夹中为request.js模块创建一个手动模拟(该文件夹区分大小写,所以不能使用_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.',
              }),
        );
      });
    }
    

    现在让我们为异步功能编写一个测试。

    // __tests__/user-test.js
    jest.mock('../request');
    
    import * as user from '../user';
    
    // The assertion for a promise must be returned.
    it('works with promises', () => {
      expect.assertions(1);
      return user.getUserName(4).then(data => expect(data).toEqual('Mark'));
    

    我们调用 jest.mock('../request') 来告诉 Jest 使用我们手动的 mock。它期望返回值是一个将被 resolved 的 Promise。你可以链接任意多的 Promise,并随时调用 expect,只要最后返回一个 Promise。

    .resolves

    这儿有一种更简洁的方式,使用 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 can be used.
    it('works with async/await', async () => {
      expect.assertions(1);
      const data = await user.getUserName(4);
      expect(data).toEqual('Mark');
    });
    
    // async/await can also be used with `.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 并在 babel.config.js 文件中启用该特性。

    错误处理

    错误可以使用 .catch 方法处理。确保添加了 expect.assertions 确保确定次数的断言调用。不然,一个 fulfilled promise 将不会导致测试失败:

    // Testing for async errors using Promise.catch.
    test('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

    这个 .rejects 工作原理类似 .resolves。如果这个 promise 是 fulfilled,这个测试将自动失败。

    // Testing for async errors using `.rejects`.
    it('tests error with rejects', () => {
      expect.assertions(1);
      return expect(user.getUserName(3)).rejects.toEqual({
        error: 'User with 3 not found.',
      });
    });
    
    // Or using async/await with `.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.',
      });
    });
    

    参考:

    expect.assertions(number) 期待断言的次数
    expect.assertions(number) 验证在测试期间调用一定数量的断言。这在测试异步代码时非常有用,以确保回调中的断言确实被调用了。

    例如,我们有一个函数 doAsync 接收两个回调 callback1callback2 ,它们将以未知的顺序异步调用它们。我们可以这样测试:

    test('doAsync calls both callbacks', () => {
      expect.assertions(2); // 期待发生两次断言
      function callback1(data) {
        expect(data).toBeTruthy();
      }
      function callback2(data) {
        expect(data).toBeTruthy();
      }
    
      doAsync(callback1, callback2);
    });
    

    expect.assertions(2) 确保实际调用了两个回调。

    相关文章

      网友评论

          本文标题:Jest - 异步例子

          本文链接:https://www.haomeiwen.com/subject/lnvosctx.html