测试异步代码

    为你的测试返回一个Promise,则Jest会等待Promise的resove状态 如果 Promise 的状态变为 rejected, 测试将会失败。

    例如,有一个名为fetchData的Promise, 假设它会返回内容为'peanut butter'的字符串 我们可以使用下面的测试代码︰

    或者,您可以在测试中使用 asyncawait。 写异步测试用例时,可以在传递给test的函数前面加上async。 例如,可以用来测试相同的 fetchData 方案︰

    1. test('the data is peanut butter', async () => {
    2. const data = await fetchData();
    3. expect(data).toBe('peanut butter');
    4. });
    5. test('the fetch fails with an error', async () => {
    6. expect.assertions(1);
    7. try {
    8. } catch (e) {
    9. expect(e).toMatch('error');
    10. }
    11. });

    你也可以将 async and await.resolves or .rejects一起使用。

    上述示例中, and await实际上是一种基于Promise的异步语法糖。

    Be sure to return (or await) the promise - if you omit the return/await statement, your test will complete before the promise returned from fetchData resolves or rejects.

    如果期望Promise被Reject,则需要使用 .catch 方法。 请确保添加 expect.assertions 来验证一定数量的断言被调用。 否则,一个fulfilled状态的Promise不会让测试用例失败。

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

    If you don’t use promises, you can use callbacks. For example, let’s say that fetchData, instead of returning a promise, expects a callback, i.e. fetches some data and calls callback(null, data) when it is complete. 你期望返回的数据是一个字符串 'peanut butter'

    默认情况下,一旦到达运行上下文底部Jest测试立即结束。 这样意味着这个测试将不能按预期工作。

    问题在于一旦fetchData执行结束,此测试就在调用回调函数前结束了(因为同步代码结束后,才是异步拿到的数据)。

    1. test('the data is peanut butter', done => {
    2. function callback(error, data) {
    3. if (error) {
    4. done(error);
    5. }
    6. try {
    7. done();
    8. } catch (error) {
    9. done(error);
    10. }
    11. }
    12. fetchData(callback);
    13. });

    done() 函数从未被调用,测试用例会正如你预期的那样执行失败(显示超时错误)。

    expect 执行失败,它会抛出一个错误,后面的 done() 不再执行。 若我们想知道测试用例为何失败,我们必须将 expect 放入 try 中,将 error 传递给 catch 中的 done函数。 否则,最后控制台将显示一个超时错误失败,不能显示我们在 expect(data) 中接收的值。

    注意: done() 不应与Promises混合,因为这会导致您测试中的内存泄漏。

    您还可以使用 .resolves 匹配器在您期望的声明,Jest 会等待这一 Promise 来解决。 如果 Promise 被拒绝,则测试将自动失败。

    一定不要忘记把整个断言作为返回值返回⸺如果你忘了return语句的话,在 fetchData 返回的这个 promise 变更为 resolved 状态、then() 有机会执行之前,测试就已经被视为已经完成了。

    1. test('the fetch fails with an error', () => {
    2. });

    上述几种异步形式没有优劣之分,你可以在你的项目或者文件中混合或单独使用他们。 这只取决于哪种形式更能使您的测试变得简单。