iplus26 iplus26 - 6 months ago 15
Node.js Question

Mocha/Should.js using asynchronous function

I'm new to JavaScript test frameworks. I would like to do a little optimization but I run into some problems. The project is using should.js

Here is the simplified version of my original test cases:

describe('Simple', function() {
describe('Test', function() {
it('should do something', function(done) {
somePromise.then(function(data) {
data.should.above(100);
done();
});
}

it('should do something else but alike', function(done) {
somePromise.then(function(data) {
data.should.above(100);
done();
});
}

}
});


I'm trying to do it this way:

var testFunc = function(data) {
it('should do something', function(done) {
data.should.above(100);
done();
});
}

describe('Simple', function() {
describe('Test', function() {
somePromise.then(function(data) {
testFunc(data);
});

somePromise.then(function(data) {
testFunc(data);
});
}
});


The promise is asynchronous, and maybe that's the reason why my "optimization" didn't work? I've found no "done" callback for
describe
function in docs.

Thanks in advance! Any help will be appreciate!

Answer

Your example does not work since Mocha has finished registering test cases when your promise resolves.

Testing the same promise with different assertions

To test a single promise using several assertions you simply need to create the promise at the start of the tests and then use it in the it blocks like the following:

describe('A module', function() {
    var promise;

    before(function () {
        promise = createPromise();
    });

    it('should do something', function() {
        return promise.then(function (value) {
            value.should.be.above(100);
        });
    });

    it('should do something else', function() {
        return promise.then(function (value) {
            value.should.be.below(200);
        });
    });
});

Note that if the promise is returned from an API call, the call will only be made once. The result is simply cached in the promise for the two test cases.

This also makes use of the fact that you can return promises from test cases instead of using a done callback. The test case will then fail if the promise is rejected or if any of the assertions in the then() calls fail.

Testing different promises with the same assertions

Assuming that you want to test different promises using the same assertions you could pass a function to testFunc that creates the promise to be tested.

var testFunc = function(promiseFactory) {
  it('should do something', function(done) {
      promiseFactory().then(function(data) {
          data.should.above(100);
          done();
      });
  });
}

describe('Simple', function() {
  describe('Test', function() {
      testFunc(function () { return createSomePromise(); });

      testFunc(function () { return createSomeOtherPromise(); });
  });
});

This works since Mocha's it function is run immediately inside the describe block. The promises are then created using the promiseFactory callback when the test cases are actually run.

As you can also return promises from test cases you can change testFunc to return an assertion as a promise like this:

var testFunc = function(promiseFactory) {
  it('should do something', function() {
      return promiseFactory().should.eventually.be.above(100);
  });
}