代码之家  ›  专栏  ›  技术社区  ›  seldon

节点。js断言。使用异步函数抛出(Promises)

  •  36
  • seldon  · 技术社区  · 8 年前

    我想检查异步函数是否使用 assert.throws 来自本地 assert 单元 我试过了

    const test = async () => await aPromise();
    assert.throws(test); // AssertionError: Missing expected exception..
    

    它(显然?)无法工作,因为函数在Promise解析之前退出。 然而我发现 this question 其中使用回调实现相同的效果。

    有什么建议吗?

    (我正在使用Babel传输到Node.js本地生成器。)

    5 回复  |  直到 4 年前
        1
  •  48
  •   Pang Mohammad Imran    4 年前

    节点10及更新版本

    自节点以来。js v10.0,有 assert.rejects 正是这样。

    节点的旧版本

    async 函数从不抛出-它们返回可能被拒绝的承诺。

    您不能使用 assert.throws 与他们一起。 您需要编写自己的异步断言 :

    async function assertThrowsAsynchronously(test, error) {
        try {
            await test();
        } catch(e) {
            if (!error || e instanceof error)
                return "everything is fine";
        }
        throw new AssertionError("Missing rejection" + (error ? " with "+error.name : ""));
    }
    

    并像这样使用它

    return assertThrowsAsynchronously(aPromise);
    

    在异步测试用例中。

        2
  •  21
  •   vitalets    6 年前

    基于 Bergi answer 我建议使用更通用的解决方案 assert.throws 错误消息:

    import assert from 'assert';
    
    async function assertThrowsAsync(fn, regExp) {
      let f = () => {};
      try {
        await fn();
      } catch(e) {
        f = () => {throw e};
      } finally {
        assert.throws(f, regExp);
      }
    }
    

    用法:

    it('should throw', async function () {
        await assertThrowsAsync(async () => await asyncTask(), /Error/);
    });
    
        3
  •  3
  •   jayWHY    6 年前

    答案是有效的,但我今天遇到了这个问题,并提出了另一个解决方案,我认为这个方案简单一些。

    // Code being tested
    async function thisFunctionThrows() {
        throw new Error('Bad response')
    }
    
    
    // In your test.
    try {
        await thisFunctionThrows()
        assert.equal(1 == 0) // Never gets run. But if it does you know it didn't throw.
    } catch (e) {
        assert(e.message.includes('Bad response'))
    }
    
        4
  •  3
  •   seldon    5 年前

    由于这个问题仍然受到关注,我想总结两个最佳解决方案,特别是强调新的标准方法。

    节点v10+

    断言库中有一个专用方法, assert.rejects .

    对于节点的旧版本

    来自的填充 vitalets answer :

    import assert from 'assert';
    
    async function assertThrowsAsync(fn, regExp) {
      let f = () => {};
      try {
        await fn();
      } catch(e) {
        f = () => {throw e};
      } finally {
        assert.throws(f, regExp);
      }
    }
    
        5
  •  0
  •   Alexander Mills    6 年前

    你要使用, assert.rejects() 这在Node中是新的。js版本10。

    在高层,而不是断言。抛出,我们想要像assert这样的东西。拒绝,希望你能接受它并运行:

            const assertRejects = (fn, options) => {
                return Promise.resolve(fn()).catch(e => {
                        return {
                            exception: e,
                            result: 'OK'
                        }
                    })
                    .then(v => {
    
                        if (!(v && v.result === 'OK')) {
                            return Promise.reject('Missing exception.');
                        }
    
                        if (!options) {
                            return;
                        }
    
                        if (options.message) {
                            // check options
                        }
    
                        console.log('here we check options');
    
                    });
            };
    
            it('should save with error', async () => {
    
                // should be an error because of duplication of unique document (see indexes in the model)
                return await assertRejects(async () => {
    
                    patientSubscriber = await PatientSubscriber.create({
                        isSubscribed: true,
                        patient: patient._id,
                        subscriber: user._id
                    });
    
                }, {
                    message: /PatientSubscriber validation failed/
                });
    
            });