Search code examples
javascriptnode.jsunit-testingassertmocha.js

assert.throws on asynchronous method


I am having troubles trying to use assert.throws in my Mocha unit tests,

I have this method:

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
  })
}

And in my unit tests I have:

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

The results I get are random, sometimes the error is being thrown (I got Uncaught Error: something went wrong) and the test is failing, sometimes it passes.

I have tried a couple of other things, such as passing the error through the callback and do:

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

And I got as output: AssertionError: Missing expected exception (Error).. so I guess he doesn't see anything...

The only way I can get assert.throws to work as I expected is with a synchronous function:

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

I was wondering if it had to do something with done(), but still even by calling it in my callback, no success. Did I miss something?


Solution

  • I managed to get it to work by improving David Norman's answer. As I stated in my question, my test lacked the done() call, but even if I was calling it after the throw err, I was having a timeout exception with Mocha. Anyway, this is the code snippet I used for the test of another asynchronous method I wrote, and it pass and does not get a timeout error:

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

    Where /No directory/ matches the text description of the Error being thrown in fn's callback. It could be Error but I wanted to be sure of wich error assert.throws was detecting.