【问题标题】:How to successfully mock and catch an error using Jest?如何使用 Jest 成功模拟和捕获错误?
【发布时间】:2019-05-15 18:22:38
【问题描述】:

几天来,我一直在尝试创建一个特定的测试,如果能深入了解我可能做错了什么,我将不胜感激。

我正在尝试模拟 Array 过滤器函数以引发错误。

userHelper.js

//filter users by email ending
const filterUsersByEmailDomain = (usersArray, emailEnding) => {
    try {
        let bizUsers = usersArray.filter(user => {
            return user.email.endsWith(emailEnding);
        });
        return bizUsers;
    } catch (err) {
        console.log('error filtering users. Throwing error.');
        throw err;
    }
}

userHelper.test.js:

it('should throw', () => {
        const user1 = {id: 1, email: 'tyler@tyler.com'};
        const user2 = {id: 2, email: 'tevin@tevin.biz'};
        const userArray = [user1, user2];
        const domainEnding = '.biz';

        Array.prototype.filter = jest.fn().mockImplementation(() => {throw new Error()});

        expect(() => {usersHelper.filterUsersByEmailDomain(userArray, domainEnding)}).toThrow();
    });

据我所知,错误被抛出,但没有被成功捕获。我也尝试过在 try catch 块中调用 usersHelper.filterUsersByEmailDomain(),就像我看到其他人所做的那样,但也没有成功。提前致谢!

编辑: 这是我在项目中本地运行此测试设置时收到的错误。

  ● Testing the usersHelper module › should throw



      56 |         const domainEnding = '.biz';
      57 | 
    > 58 |         Array.prototype.filter = jest.fn().mockImplementation(() => {throw new Error()});
         |                                                                            ^
      59 | 
      60 |         expect(() => {usersHelper.filterUsersByEmailDomain(userArray, domainEnding)}).toThrow();
      61 |     });

      at Array.filter.jest.fn.mockImplementation (utils/__tests__/usersHelper.test.js:58:76)
      at _objectSpread (node_modules/expect/build/index.js:60:46)
      at Object.throwingMatcher [as toThrow] (node_modules/expect/build/index.js:264:19)
      at Object.toThrow (utils/__tests__/usersHelper.test.js:60:87)

(node:32672) UnhandledPromiseRejectionWarning: Error
(node:32672) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .c
atch(). (rejection id: 2)
(node:32672) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

【问题讨论】:

  • 我建议你试试spyOn,就像const spy = jest.spyOn(userArray, 'filter').mockImplementation(() => throw new Error())一样。 jestjs.io/docs/en/jest-object#jestspyonobject-methodname
  • 我已经设置了测试repl.it/repls/MedicalIntelligentTriangles,它似乎工作正常
  • @Teneff 嗯,这很奇怪。您在上面发布的 repl.it 示例似乎也对我有用。但是,当我在本地运行此测试时,我仍然会遇到错误:( 我已经编辑了帖子以包含我遇到的错误。

标签: javascript node.js unit-testing jestjs


【解决方案1】:

Array.prototype.filter 是一个非常底层的函数,模拟它以引发错误可能会导致您的测试无法正常运行。

做这个简单的测试:

it('should throw', () => {
  expect(() => { throw new Error() }).toThrow();  // Success!
});

...效果很好...

...但是模拟Array.prototype.filter 抛出错误并失败:

it('should throw', () => {
  Array.prototype.filter = jest.fn(() => { throw new Error() });
  expect(() => { throw new Error() }).toThrow();  // Fail!
});

相反,只需在数组本身上模拟 filter

it('should throw', () => {
  const user1 = { id: 1, email: 'tyler@tyler.com' };
  const user2 = { id: 2, email: 'tevin@tevin.biz' };
  const userArray = [user1, user2];
  const domainEnding = '.biz';

  userArray.filter = () => { throw new Error() };  // <= mock filter on userArray

  expect(() => { usersHelper.filterUsersByEmailDomain(userArray, domainEnding) }).toThrow();  // Success!
});

JavaScript 在检查其原型之前会在对象本身上查找一个属性,因此 userArray 上的模拟 filterfilterUsersByEmailDomain 中被调用,并且测试按预期通过。

【讨论】:

  • 谢谢你,成功了!很好的解释。我唯一调整的是函数的模拟。 userArray.filter = jest.fn().mockImplementation(() =&gt; {throw new Error()});
【解决方案2】:

你想把你的toThrow() 放在测试函数的执行之前,在 Jest 'toX' 中意味着它必须预先设置,例如:toBeCalled()。这就是toHaveBeenCalled() 存在的原因,因为这种形式允许在代码运行后进行断言。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-27
    • 2019-09-18
    • 2022-08-09
    • 2020-08-01
    • 1970-01-01
    • 2018-01-18
    • 2021-10-10
    • 2019-01-20
    相关资源
    最近更新 更多