Node.js assert.throws 带有异步函数(Promises)
Posted
技术标签:
【中文标题】Node.js assert.throws 带有异步函数(Promises)【英文标题】:Node.js assert.throws with async functions (Promises) 【发布时间】:2016-06-17 09:13:46 【问题描述】:我想检查是否使用原生 assert
模块中的 assert.throws
引发了异步函数。
我试过了
const test = async () => await aPromise();
assert.throws(test); // AssertionError: Missing expected exception..
它(显然?)不起作用,因为函数在 Promise 解决之前退出。 然而我发现this question 使用回调实现了同样的事情。
有什么建议吗?
(我正在使用 Babel 转换为 Node.js 原生生成器。)
【问题讨论】:
【参考方案1】:节点 10 和更新的节点
从 Node.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);
在异步测试用例中。
【讨论】:
这是不必要的,因为assert.throws
已经返回了一个行为与此完全相同的承诺
@Ali 您在使用哪个assert.throws
? native node.js one 既不返回承诺,也不处理返回承诺的函数
这是原生的。至少在节点 v8 中。它没有记录在案,但这就是它正在做的事情。
@Ali No, it doesn't?
是的,它没有。对困惑感到抱歉。我们正在使用来自npm
的assert-throws-async
并替换本机assert.throws
。我错过了它,因为原始文件已替换为不同的文件,并且无需在我的文件中重新导入 assert-throws-async
即可工作。【参考方案2】:
基于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/);
);
【讨论】:
优秀的解决方案,希望能成为官方断言库! 你是我的英雄! 是的,不要在 2018 年及以后使用这个,使用assert.rejects()
,这里:nodejs.org/api/…【参考方案3】:
给出的答案有效,但我今天遇到了这个问题并想出了另一个解决方案,我认为它更简单一些。
// 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'))
【讨论】:
由于我使用的是较早版本的 Node ( 【参考方案4】:由于这个问题仍然受到关注,我想总结两个最佳解决方案,特别是强调新的标准方法。
节点 v10+
断言库中有一个专用方法,assert.rejects
。
对于旧版本的 Node
来自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】:您将要使用 assert.rejects()
,这是 Node.js 版本 10 中的新功能。
在高层次上,我们想要的是 assert.rejects 之类的东西,而不是 assert.throws,希望你能接受并运行它:
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/
);
);
【讨论】:
以上是关于Node.js assert.throws 带有异步函数(Promises)的主要内容,如果未能解决你的问题,请参考以下文章
使用带有 Javascript 的 MySQL (node.js)
node.js - 带有 base64 的 http [重复]