2

I made a very simple RESTful API that allows users to add, delete and update information about Hogwarts students. Mongo acts as the persistence layer.

A GET request to url/students is supposed to return a list of all student objects. While writing the test for it I wrote

expect(res).to.equal('student list');

This is just for an initial check to make sure the test would fail but it isn't instead I get this error:

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): AssertionError: expected { Object (domain, _events, ...) } to equal 'student list'

So it knows that the two values are different but instead of the test failing it's throwing an error. I've pasted the full test code below.

let chai = require('chai');
let chaiHttp = require('chai-http');
var MongoClient = require('mongodb').MongoClient;
chai.use(chaiHttp);
const expect = chai.expect;

describe('Students', async () => {
  describe('/GET students', () => {
    it('should GET all the students', async () => {
      chai.request('http://localhost:5000')
        .get('/students')
        .then(function (res) {
          try {
            expect(res).to.equal('hola');
          } catch (err) {
            throw err;
          }
        })
        .catch(err => {
          throw err; //this gets thrown
        })
    });
  });
});

And if you can show me the syntax of properly using async await for writing these tests please do that too.

Brian Adams
  • 43,011
  • 9
  • 113
  • 111
Anant Sinha
  • 159
  • 1
  • 10
  • .catch() after then(...). Note: async statement make sense only if you use the await statement – FrV Apr 05 '19 at 18:33
  • That doesn't work, I'll update the code above though. After I added the .catch, it caught the AssertionError but the point is why is there an AssertionError at all? – Anant Sinha Apr 05 '19 at 18:41
  • console.log res, if res != "hola", AssertionError is thrown – FrV Apr 05 '19 at 18:46
  • res is supposed to be an object, but the expect should fail the test, why should there be an error? Why is the test not failing ? – Anant Sinha Apr 05 '19 at 18:58
  • try a sample `it('should be true', ()=>expect(false).to.equal(true))` , if it works like you want and not your example, that's because of the promise. Maybe you can check this: https://stackoverflow.com/questions/55520801/how-to-wrap-errors-from-third-party-api/55521013#55521013 – FrV Apr 05 '19 at 19:06

1 Answers1

2

The test passes and logs the "Unhandled promise rejection" warning because the error is thrown within a Promise which just causes the Promise to reject.

Since the Promise is not returned or await-ed, the test completes successfully...

...and because nothing is waiting for or handling the rejected Promise, Node.js logs a warning.

Details

An error thrown in a test will fail the test:

it('will fail', function () {
  throw new Error('the error');
});

...but a rejected Promise will not fail the test if it is not returned or await-ed:

it('will pass with "Unhandled promise rejection."', function() {
  Promise.reject(new Error('the error'));
});

.catch returns a Promise so throwing in a .catch returns a rejected Promise, but if that Promise is not returned or await-ed then the test will also pass:

it('will also pass with "Unhandled promise rejection."', function() {
  Promise.reject(new Error('the error')).catch(err => { throw err });
});

...but if a rejected Promise is returned or await-ed then the test will fail:

it('will fail', async function() {
  await Promise.reject(new Error('the error'));
});

And if you can show me the syntax of properly using async await for writing these tests please do that too.

For your test you can simplify it to this:

const chai = require('chai');
const expect = chai.expect;
const chaiHttp = require('chai-http');
chai.use(chaiHttp);

describe('Students', async function() {
  describe('/GET students', function() {
    it('should GET all the students', async function() {
      const res = await chai.request('http://localhost:5000').get('/students');
      expect(res).to.equal('hola');  // <= this will fail as expected
    });
  });
});

Details

From the chai-http doc:

If Promise is available, request() becomes a Promise capable library

...so chai.request(...).get(...) returns a Promise.

You can simply await the Promise and the test will wait until the Promise resolves before continuing.

Brian Adams
  • 43,011
  • 9
  • 113
  • 111