Reputation: 2261
I have the following validation function checking if a user exists:
validate.user = async (user, password) => {
const matches = await bcrypt.compare(password, user.password);
if (matches) return user;
if (!matches) {
return validate.logAndThrow('User password does not match');
}
return validate.logAndThrow('Error in bcrypt compare');
};
The following test using Chai should test this:
chai.use(sinonChai);
const { expect } = chai;
describe('#user', () => {
it('show throw if user is undefined', () => {
expect(() => validate.user(undefined, 'pass')).to.throw('User does not exist');
});
The error does get thrown, however mocha shows the following in the console:
2) show throw if user is undefined (node:18587) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: User does not exist
So my question is, how I can rewrite the test such that it does catch promise rejections?
Upvotes: 0
Views: 1294
Reputation: 1388
For testing promise-based functions (async) use chai-as-promised plugin:
expect(validate.user(undefined, 'pass')).to.be.rejectedWith(Error, 'User does not exist');
In this case you do not put () => validate.user()
into expect
because it will not return a promise. async
functions always return a promise, so it's enough to just call your method inside expect
(without wrapping it into a method).
I hope this is clear :) If you have any questions - feel free to ask.
Upvotes: 1
Reputation: 938
Im not totally sure it is mocha that throws that unhandled rejection.
I think it is your bcrypt.compare which is async by nature and uses callbacks. await
can't really be used out of the box with async functions.
but you can promisify the async calls with nodes util
library like this:
const util = require('util');
const bcrypt = require('bcrypt');
const bcryptCompare = util.promisify(bcrypt.compare);
Now you can use await bcryptCompare(password, user.password);
like you intended. please note that i changed the constant after the await call.
Also to handle rejections with async/await
you should use try/catch
like this:
let matches;
try {
matches = await bcryptCompare(password, user.password);
} catch(bcryptError) {
throw new Error(bcryptError);
}
Upvotes: 1