zoukankan      html  css  js  c++  java
  • 前端测试框架Jest系列教程 -- Asynchronous(测试异步代码)

    写在前面:

      在JavaScript代码中,异步运行是很常见的。当你有异步运行的代码时,Jest需要知道它测试的代码何时完成,然后才能继续进行另一个测试。Jest提供了几种方法来处理这个问题。

    测试异步代码的三种实现方式:

    方法一:回调函数

    这是非常常见的通用处理方式,比如你有一个fetchData(callback)的function用来获取数据,并且在获取完成的时候调用callback 函数,你想测试返回的数据是“peanut butter” ,默认情况下当fetchData执行完成的时候Jest的测试就完成了,这并不是你所期望的那样的去运行。

    // Don't do this!
    test('the data is peanut butter', () => {
      function callback(data) {
        expect(data).toBe('peanut butter');
      }
    
      fetchData(callback);
    });

    上面代码的问题就在于一旦fetchData完成,测试也就执行完成,然后再调用回调。

    Jest提供了一种用于测试的实现方式,下面代码 done() 被执行则意味着callback函数被调用。 

    test('the data is peanut butter', done => {
      function callback(data) {
        expect(data).toBe('peanut butter');
        done();
      }
    
      fetchData(callback);
    });

    如果 done 永远都不被调用,那么的测试将会失败,这也正是我们期望的(我们希望callback被调用,并且返回的data是我们期望的值)

    方法二:承诺验证

    如果你的代码中使用了承诺的方式,处理异步测试将会变得更加简单。Jest从你的测试中返回一个承诺,然后等待承诺被实现,如果没有实现,那么就判断测试是失败的。

    还是上面的例子,如果用承诺验证,那么实现将是下面的样子:

    test('the data is peanut butter', () => {
      expect.assertions(1);
      return fetchData().then(data => {
        expect(data).toBe('peanut butter');
      });
    });

    assertions(1)代表的是在当前的测试中至少有一个断言是被调用的,否则判定为失败。

    如果删掉return语句,那么你的测试将在fetchData完成之前结束。

    如果断言的承诺并没有被实现,那么你可以添加 .catch 方法。一定要添加expect,断言验证一定数量的断言被调用。否则一个实现的承诺就不会失败。

    test('the fetch fails with an error', () => {
      expect.assertions(1);
      return fetchData().catch(e => expect(e).toMatch('error'));
    });

    在Jest 20.0.0+  的版本中你可以使用 .resolves 匹配器在你的expect语句中,Jest将会等待一直到承诺被实现,如果承诺没有被实现,测试将自动失败。

    test('the data is peanut butter', () => {
      expect.assertions(1);
      return expect(fetchData()).resolves.toBe('peanut butter');
    });

    如果你期望你的承诺是不被实现的,你可以使用 .rejects ,它的原理和 .resolves类似

    test('the fetch fails with an error', () => {
      expect.assertions(1);
      return expect(fetchData()).rejects.toMatch('error');
    });

    第三种:使用 Async/Await

    我相信大家最Async/Await 是比较熟悉的,你可以在测试中使用异步和等待。要编写一个async测试,只需在传递到测试的函数前面使用async关键字。例如上面同样的fetchData场景可以使用下面的实现:

    test('the data is peanut butter', async () => {
      expect.assertions(1);
      const data = await fetchData();
      expect(data).toBe('peanut butter');
    });
    
    test('the fetch fails with an error', async () => {
      expect.assertions(1);
      try {
        await fetchData();
      } catch (e) {
        expect(e).toMatch('error');
      }
    });

    当然你也可以将Async Await和 .resolves  .rejects 结合起来(Jest 20.0.0+  的版本)

    test('the data is peanut butter', async () => {
      expect.assertions(1);
      await expect(fetchData()).resolves.toBe('peanut butter');
    });
    
    test('the fetch fails with an error', async () => {
      expect.assertions(1);
      await expect(fetchData()).rejects.toMatch('error');
    });

    写在最后:

    在这些情况下,异步和等待实际上只是与承诺示例使用的相同逻辑的语法糖。


    这几种方法中没有一个特别优于另外一个,你可以将它们组合在一个代码库中,甚至可以在单个文件中进行匹配。它只是取决于哪种样式使你的测试更简单。

    系列教程:

       1. 前端测试框架Jest系列教程 -- Matchers(匹配器)

       2.前端测试框架Jest系列教程 -- Asynchronous(测试异步代码)

       3.前端测试框架Jest系列教程 -- Mock Functions(模拟器)

       4.前端测试框架Jest系列教程 -- Global Functions(全局函数)

  • 相关阅读:
    OnSharedPreferenceChangeListener不被调用原理及解决方案
    自测题的整理(持续更新)
    排序的练习题
    C++各种类型的简单排序大汇总~
    洛谷P1540 机器翻译
    队列
    文件和结构体
    洛谷P1079 Vigenère 密码
    洛谷P1328生活大爆炸版石头剪刀布
    洛谷P1553数字反转升级版
  • 原文地址:https://www.cnblogs.com/Wolfmanlq/p/8017021.html
Copyright © 2011-2022 走看看