1

I've had a small issue that bothers me.. The following code shows an async test, in that test we test a code we have no control of (blackbox for the test, I can change it).

The blackbox code dispatches event when it's done, the test listens to this event and asserts the data.

the problem is when there is an assertion error, exception is thrown and cought by the promise error handler and not by the test framework, so the done function is never executes and we get timeout error for this test.

its easy to solve it by try & catch inside the it() block, but is it a good practice to ALWAYS have try & catch inside the it() block? so far I trusted the test framework to deal with exceptions

another problem, is that the error is silent, unless the catch prints it, and since its blackbox we cannot count on it.

the tips here helped me solve it, but I dont like the solutions: https://github.com/mochajs/mocha/issues/1128#issuecomment-40866763

it is different than other similar questions because in the it() block we dont have any reference to a promise object.

describe.only("test", function () {

  var event;

  // blackbox simulates a code we have no controler over
  // inside this code we have a promise, when this promise resolves it triggers event
  var blackbox = function () {
    var promise = new Promise(function (resolve, reject) {
      resolve();
    });

    promise.then(function () {
      event(4);
    }).catch(function (e) {
      console.log(e);
    });
  };

  it("async with blackbox promise", function (done) {
    // this simulates event listenner, when the event is triggered the code executes
    event = function (data) {
      // this assertion works and everything is fine
      data.should.be.equal(4);
      // this assertion thrown exception that is being cought by the promise reject handler and
      // isnt cought by the testing framework (chai / mocha)
      data.should.be.equal(5);
      // because the exception is thrown we never reach the done
      done();
    };

    blackbox();

  });
});
Nir Cohen
  • 75
  • 7
  • I think you are mixing up a bit of things. Always return your promises, and when testing promises you do not need the `done` callback. Just return all the promises you have. – MarcoL Nov 15 '16 at 17:00
  • Also note that if you want `mocha` to fail on a rejected `promise`, then you do not have to `catch` yourself. – MarcoL Nov 15 '16 at 17:01
  • @MarcoL, this is just an example, since the code is blackboxed - I dont have control over it. it can be a 3rd party lib / dependency or do you mean the blackbox example code is written wrong? – Nir Cohen Nov 16 '16 at 12:01
  • If the code (from 3rd parties or black boxed) deals with promises then it should return promises to you. – MarcoL Nov 16 '16 at 22:45
  • If the blackbox doesn't return you nothing, you cannot do async testing here. Also, the fact that internally it uses Promises instead of callbacks doesn't matter at all if it doesn't give you the option to handle them. – MarcoL Nov 21 '16 at 07:51
  • This is similar to this question: http://stackoverflow.com/questions/39716569/nodejs-unhandledpromiserejectionwarning – Gyuri Jan 04 '17 at 23:46

1 Answers1

1

The way you test promises in mocha is that you return them and let it do the job of decided when to fail or not.

So the first step is to make the promise available in your blackbox function:

// blackbox simulates a code we have no controler over
// inside this code we have a promise, when this promise resolves it triggers event
var blackbox = function () {
  var promise = new Promise(function (resolve, reject) {
    resolve();
  });

  return promise.then(function () {
    event(4);
  });
  // do not catch here unless you want the test to not fail on error
};

Now let's change the test code to handle promises:

it("async with blackbox promise", function () {
  // this simulates event listenner, when the event is triggered the code executes
  event = function (data) {
    // this assertion works and everything is fine
    data.should.be.equal(4);
    // this assertion thrown exception that is being cought by the promise reject handler
    data.should.be.equal(5);
  };
  // mocha will append a rejection handler to this promise here and fail if it gets called
  return blackbox();

});
MarcoL
  • 9,829
  • 3
  • 37
  • 50