如何测试异步函数以开玩笑地抛出异常
#javascript #网络开发人员 #jest #unittest

作为任何好的开发人员,您都应始终测试您的代码。
作为任何好的开发人员,您都应始终尝试捕获异常并在编写功能时处理错误。

例如,如果您有这样的函数:

export const logName = name => {
  // do something with the name
};

以上功能期望您始终定义一个名称,但不能保证,因此您应该做的是处理名称不确定的情况,并在这种情况下施加例外,并且您的功能应看起来这样:


export const funThatThrows = name => {
    if (!name) {
        throw new Error('You need the name');
    }

    // do something with name
};

,如果要测试函数如果未传递的函数给您一个例外的情况,通常您会做的是编写这样的测试:

describe('funThatThrows', () => {
  it('should throw an error if name is missing', () => {
    expect(() => {
      funThatThrows();
    }).toThrow();
  });
});

本质上,您在传递给expect的匿名函数中运行函数,然后检查是否会使用toThrow方法引发异常。

但是,您如何通过返回承诺的功能对其进行测试呢?

现在,如果您的函数不是立即执行,则必须运行某些异步,并仅在解决值时返回该值,也许是这样的:

export const funThatThrowsAsync = async name => {
  if (!name) {
    throw new Error('You need the name');
  }
  return Promise.resolve(`hello ${name}`);
};

,如果您尝试将async/await添加到我们之前所做的测试中,也许是这样:

describe('funThatThrowsAsync', () => {
  it('should throw an error if name is missing', () => {
    expect(async () => {
      await funThatThrowsAsync();
    }).toThrow();
  });
});

上面的问题是,以上只是在外壳中丢弃错误而不是通过,并使测试失败:

throw new Error('You need the name');
          ^
Error: You need the name

您需要做的使测试工作的工作是在.toThrow()之前附加.rejects方法,从本质上讲具有此公式:

expect(function).rejects.toThrow()

这将告诉Jest您的功能期望丢弃错误,并且会使控制台中的错误保持沉默。
因此,我们的测试应像这样重写:

describe('funThatThrowsAsync', () => {
  it('should throw an error if name is missing', () => {
    expect(async () => {
      await funThatThrowsAsync();
    }).rejects.toThrow();
  });
});

现在您的测试将通过!

 PASS  src/async/async.test.js
  Test throw with Async/Await
    funThatThrows
      ✓ should throw an error if name is missing (8 ms)
    funThatThrowsAsync
      ✓ should throw an error if name is missing (3 ms)

有关更多信息,您可以查看official documentation