assert.throws在异步方法上

时间:2013-10-04 17:16:16

标签: javascript node.js unit-testing assert mocha

我在Mocha单元测试中尝试使用assert.throws时遇到了麻烦,

我有这个方法:

var getMetadatas = function (file, callback) {
  fs.readFile(file, {encoding: 'utf-8'}, function(err, data){
    // stuff
      if (somethingWentWrong) 
        throw new Error('Something went wrong')
    // callback call
  })
}

在我的单元测试中,我有:

it('should throw an error when passing a bad formatted file', function(){ 
  assert.throws(
    getMetadatas('someBadFormattedFile', function(metadatas){})
  )
})

我得到的结果是随机的,有时会抛出错误(我得到Uncaught Error: something went wrong)并且测试失败,有时它会通过。

我尝试过其他一些事情,例如通过回调传递错误并执行:

var fn = function(){ 
  parse.getMetadatas('test/test_incorrect.md', function (err, metas) {
      if (err) throw err
  })
}
assert.throws( function() { fn() }, Error )

我得到了输出:AssertionError: Missing expected exception (Error)..所以我猜他没有看到任何东西......

我可以按照我的预期让assert.throws工作的唯一方法是使用同步功能:

assert.throws(
  function () {throw new Error('error')}
)

我想知道它是否必须对done()执行某些操作,但即使在回调中调用它也没有成功。我错过了什么吗?

3 个答案:

答案 0 :(得分:2)

这是正确的代码

var fn = function(){ 
  parse.getMetadatas('test/test_incorrect.md', function (err, metas) {
      if (err) throw err
  })
}
assert.throws( function() { fn() }, Error )

消息

AssertionError: Missing expected exception (Error)..

说错误的异常类型被抛出。您没有说明您正在使用哪个断言,但可能是assert.throws中的“错误”指定了预期的异常类型。您需要更改它以匹配抛出的实际异常。

我想消息也可能说实际上没有抛出任何异常。您需要检查库的文档或编写一个简单的测试来检查错误。

答案 1 :(得分:1)

如果我们删除注释,那么这很简单,只有3-4行代码。您只需要遵循我在下面介绍的特定模式即可。

it('Should throw error from an asynchronous function', async function() {
   
    try {
        await someAsycnFunction();

        /**
         * The next line provokes the non-throwing someAsyncFunction() to force
         * the test fail in case someAsyncFucntion() does not throw.
         */
        assert.fail('The expected Error was not thrown.');

    } catch (err) {

        /**
         * (optional) Here we assert the error object prototype name for the cases when we
         * want to check the error type is the expected one (e.g. we have
         * extended the base JS exception to make our own exception).
         */
        assert.typeOf(err, 'Error', 'someAsycnFunction did not throw expected error.');

        /**
         * (optional) Here we assert that the error message is the expected one.
         */
        assert.include(err.message, 'ExpectedErrorMessage', 'someAsycnFunction error message does not match the expected one.');

        /**
         * (optional) Here we re-throw the caught error to assert it includes the
         * expected error message substring (as a regex). 
         */
        assert.throws(() => {
            throw err;
        }, Error, /ExpectedErrorMessage/);
    }

});

最基本的实现可能只在catch块中包含您选择的一个断言。这种方法的关键是将引发异常的函数包装在try/catch中,并在try块中强制测试失败。

答案 2 :(得分:0)

我设法通过改进大卫诺曼的答案来实现它。正如我在我的问题中所述,我的测试缺少done()调用,但即使我在throw err之后调用它,我也遇到了Mocha的超时异常。无论如何,这是我用于测试我编写的另一个异步方法的代码片段,它传递并且没有得到超时错误:

var fn = function () {
  fs.rmrf(path.join(pathDir, 'non', 'existing'), function (err) {
    done()
    assert.ifError(err)
  })
}
assert.throws(function () { fn() } , /No directory/)

/No directory/匹配fn回调中引发错误的文字说明。它可能是Error,但我想确定错误assert.throws正在检测到。