Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mocha times out on failed assertions with Q promises

Why does mocha timeout when an assertion fails inside a Q future? You also don't get to see the assertion failure when this happens. This does not happen if I just use callbacks. How should I write this while still using futures but get to see the assertion error instead of a timeout?

var Q = require('q');
function hack() {
  var ret = Q.defer();
  ret.resolve(true);
  return ret.promise;
}

it('test', function(done) {
  hack().then(function(bool) {
    assert(false);
    done();
  });
});
like image 953
Verhogen Avatar asked Jun 02 '14 01:06

Verhogen


3 Answers

The assertion call throws an exception, which is caught by Q in order to properly conform to the promises spec. So mocha never reaches done(), nor does it see an exception thrown. You could do something like this:

it('test', function(done) {
  hack().then(function(bool) {
    assert(false);
    done();
  }).catch(function(err){
    done(err);
  });
});

[edit] Alternatively, you can omit the done argument altogether and just return the promise directly from the test function, in which case mocha will pass/fail the test based on the outcome of the returned promise:

it('test', function() {
  return hack().then(function(bool) {
    assert(false);
  });
});

...which is a nice way to simplify your test functions. Props to Taytay elsewhere in this thread for pointing this out.

like image 97
greim Avatar answered Sep 29 '22 07:09

greim


Mocha now supports promises in unit tests, so you can just return the promise instead of relying upon calling (done) from a then handler. It's easier and safer (because you won't forget to call done)

So you could just write:

it('test', function() {
  return hack().then(function(bool) {
    assert(false);
  });
});

That would fail because the promise would fail, and Mocha would detect it.

This is from the Mocha docs in the section "Working with Promises": https://mochajs.org/

like image 33
Taytay Avatar answered Sep 29 '22 07:09

Taytay


Improving on greim's answer including what callumacrae added in a comment, you can do it like this:

it('test', function(done) {
  hack().then(function(bool) {
    assert(false);
    done();
  }).catch(done);
});
like image 26
Benjamin Kaiser Avatar answered Sep 29 '22 08:09

Benjamin Kaiser