How to check promises with mocha and tea?

The following test behaves strangely:

it('Should return the exchange rates for btc_ltc', function(done) { var pair = 'btc_ltc'; shapeshift.getRate(pair) .then(function(data){ expect(data.pair).to.equal(pair); expect(data.rate).to.have.length(400); done(); }) .catch(function(err){ //this should really be `.catch` for a failed request, but //instead it looks like chai is picking this up when a test fails done(err); }) }); 

How to properly process a rejected promise (and check it)?

How to handle a failed test (for example: expect(data.rate).to.have.length(400); ;?

Here is the implementation I'm testing:

 var requestp = require('request-promise'); var shapeshift = module.exports = {}; var url = 'http://shapeshift.io'; shapeshift.getRate = function(pair){ return requestp({ url: url + '/rate/' + pair, json: true }); }; 
+139
promise mocha chai
Oct 26 '14 at 8:53
source share
4 answers

The easiest way would be to use the built-in promise support that Mocha has in recent versions:

 it('Should return the exchange rates for btc_ltc', function() { // no done var pair = 'btc_ltc'; // note the return return shapeshift.getRate(pair).then(function(data){ expect(data.pair).to.equal(pair); expect(data.rate).to.have.length(400); });// no catch, it'll figure it out since the promise is rejected }); 

Or with a modern node and async / wait:

 it('Should return the exchange rates for btc_ltc', async () => { // no done const pair = 'btc_ltc'; const data = await shapeshift.getRate(pair); expect(data.pair).to.equal(pair); expect(data.rate).to.have.length(400); }); 

Since this approach promises to the end, it is easier to test, and you don’t have to think about strange cases that you think of as odd calls made done() whole world.

This is the advantage that Piss has in relation to other libraries, such as Jasmine. You can also check out Chai As Promised, which would make it even easier (no .then ), but personally I prefer the clarity and simplicity of the current version

+218
Oct 26 '14 at 11:26
source share

As already mentioned here , newer versions of Mocha are already promised. But since the OP specifically asked a question about Tea, it’s fair to mention the chai-as-promised package, which provides clean syntax for testing promises:

using chai-as-promised

Here you can use the chai-as-promised for testing cases of resolve and reject for Promise:

 var chai = require('chai'); var expect = chai.expect; var chaiAsPromised = require("chai-as-promised"); chai.use(chaiAsPromised); ... it('resolves as promised', function() { return expect(Promise.resolve('woof')).to.eventually.equal('woof'); }); it('rejects as promised', function() { return expect(Promise.reject('caw')).to.be.rejectedWith('caw'); }); 

without chai-as-promised

To make it really clear what is being tested, here the same example is encoded without chai-as-promised:

 it('resolves as promised', function() { return Promise.resolve("woof") .then(function(m) { expect(m).to.equal('woof'); }) .catch(function(m) { throw new Error('was not supposed to fail'); }) ; }); it('rejects as promised', function() { return Promise.reject("caw") .then(function(m) { throw new Error('was not supposed to succeed'); }) .catch(function(m) { expect(m).to.equal('caw'); }) ; }); 
+39
Nov 28 '16 at 10:30
source share

Here is my take:

  • using async/await
  • no additional chai modules needed
  • avoiding the catch problem, @TheCrazyProgrammer pointed out above

A function with a promise delay that fails if a delay of 0 is specified:

 const timeoutPromise = (time) => { return new Promise((resolve, reject) => { if (time === 0) reject({ 'message': 'invalid time 0' }) setTimeout(() => resolve('done', time)) }) } // ↓ ↓ ↓ it('promise selftest', async () => { // positive test let r = await timeoutPromise(500) assert.equal(r, 'done') // negative test try { await timeoutPromise(0) // a failing assert here is a bad idea, since it would lead into the catch clause… } catch (err) { // optional, check for specific error (or error.type, error. message to contain …) assert.deepEqual(err, { 'message': 'invalid time 0' }) return // this is important } assert.isOk(false, 'timeOut must throw') log('last') }) 

A positive test is pretty simple. An unexpected failure (simulation at 500β†’0 ) will automatically end the test, as rejected promises will increase.

A negative test uses the idea of ​​try-catch. However: a "complaint" of an unwanted pass occurs only after the catch clause (thus, it does not end in the catch () clause, causing further, but misleading errors.

For this strategy to work, you need to return the test from the catch clause. If you do not want to test anything, use another () -block.

+2
Jun 22 '18 at 11:15
source share

Tehre is the best solution. Just return an error with done in the catch block.

 // ... it('fail', (done) => { // any async call that will return a Promise ajaxJson({}) .then((req) => { expect(1).to.equal(11); //this will throw a error done(); //this will resove the test if there is no error }).catch((e) => { done(e); //this will catch the thrown error }); }); 

this test fails with the following message: AssertionError: expected 1 to equal 11

+1
Apr 6 '19 at 19:39
source share



All Articles