最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Unhandled promise rejection warning with Mocha, Chai and Sinon - Stack Overflow

programmeradmin9浏览0评论

I'm using Node and have the following ES6 class:

const moment = require('moment');

const sqlFileReader = require('../database/SqlFileReader');
const Lnfe = require('../errors/LoanNotFoundError');

const epoch = '1970-01-01';

/**
 * Take the input params and return the clientId (either found via loanId or untouched) and dateString we need
*/
class ParameterParser {

static async prepareInputParameters(con, req) {

    let clientId = req.query.client_id; // Will be overriden if we need and are able to obtain the client id via loan id.
    let dateString;

    // If no client_id is given but loan_id is, get the client_id via loan_id:
    if (typeof req.query.client_id === 'undefined' && typeof req.query.loan_id !== 'undefined') {
        const { retData } = await sqlFileReader.read('./src/database/sql/getClientIdFromLoanId.sql', [`${req.query.loan_id}`], con, req.logger);
        if (retData.rowsCount > 0) {
            clientId = retData.rows[0].client_id;
        }
        else {
            throw new Lnfe(400, req);
        }
    }

    if (typeof req.queryplaint_init_date === 'undefined') {
        dateString = epoch;
    }
    else {
        // Need to subtract 6 years from the plaint_init_date:
        dateString = moment(moment(req.queryplaint_init_date, 'YYYY-MM-DD').toDate()).subtract(6, 'years').format('YYYY-MM-DD');
    }

    return { clientId, dateString };
}

}

module.exports = ParameterParser;

I am testing it using Mocha, Chai, Chai-as-Promised and Sinon:

'use strict';

const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const sinon = require('sinon');

const parameterParser = require('../../src/core/ParameterParser.js');
const sqlFileReader = require('../../src/database/SqlFileReader.js');
const Lnfe = require('../../src/errors/LoanNotFoundError');

chai.use(chaiAsPromised);
const { expect } = chai;

const retData = {
rowsCount: 1,
rows: [{ client_id: 872 }],
};

const reqDateAndLoan = {
query: {
    plaint_init_date: '2022-03-15',
    loan_id: '1773266',
},
};

const reqDateAndClient = {
query: {
    plaint_init_date: '2022-03-15',
    client_id: '872',
},
};

const reqDateAndLoanIdThatDoesNotExist = {
query: {
    plaint_init_date: '2022-03-15',
    loan_id: '1773266999999999999',
},
};

describe('prepareInputParameters', () => {

sinon.stub(sqlFileReader, 'read').returns({ retData });

it('results in correct client id and date string', async () => {
    const ret = { clientId: 872, dateString: '2016-03-15' };
    expect(await parameterParser.prepareInputParameters(null, reqDateAndLoan)).to.deep.equal(ret);
});

it('results in a client id equal to the that input if the request query contains a client id', async () => {
    const ret = { clientId: '872', dateString: '2016-03-15' };
    expect(await parameterParser.prepareInputParameters(null, reqDateAndClient)).to.deep.equal(ret);
});

it('throws a \'Loan Not Found\' error', async () => {
    expect(parameterParser.prepareInputParameters(null, reqDateAndLoanIdThatDoesNotExist)).eventually.throw(Lnfe, 400, 'Loan Not Found');
});

it('DOES NOT throw a \'Loan Not Found\' error', async () => {
    expect(async () => {
        await parameterParser.prepareInputParameters(null, reqDateAndLoanIdThatDoesNotExist);
    }).to.not.throw(Lnfe, 400, 'Loan Not Found');
});


});

The tests pass but the output has an couple of node warnings:

prepareInputParameters
✓ results in correct client id and date string
✓ results in a client id equal to the that input if the request query contains a client id
✓ throws a 'Loan Not Found' error
(node:23875) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): AssertionError: Loan Not Found: expected { Object (clientId, dateString) } to be a function
(node:23875) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
✓ DOES NOT throw a 'Loan Not Found' error


4 passing (19ms)

Any ideas how I can get rid of these warnings or what I'm doing wrong?

I'm using Node and have the following ES6 class:

const moment = require('moment');

const sqlFileReader = require('../database/SqlFileReader');
const Lnfe = require('../errors/LoanNotFoundError');

const epoch = '1970-01-01';

/**
 * Take the input params and return the clientId (either found via loanId or untouched) and dateString we need
*/
class ParameterParser {

static async prepareInputParameters(con, req) {

    let clientId = req.query.client_id; // Will be overriden if we need and are able to obtain the client id via loan id.
    let dateString;

    // If no client_id is given but loan_id is, get the client_id via loan_id:
    if (typeof req.query.client_id === 'undefined' && typeof req.query.loan_id !== 'undefined') {
        const { retData } = await sqlFileReader.read('./src/database/sql/getClientIdFromLoanId.sql', [`${req.query.loan_id}`], con, req.logger);
        if (retData.rowsCount > 0) {
            clientId = retData.rows[0].client_id;
        }
        else {
            throw new Lnfe(400, req);
        }
    }

    if (typeof req.query.plaint_init_date === 'undefined') {
        dateString = epoch;
    }
    else {
        // Need to subtract 6 years from the plaint_init_date:
        dateString = moment(moment(req.query.plaint_init_date, 'YYYY-MM-DD').toDate()).subtract(6, 'years').format('YYYY-MM-DD');
    }

    return { clientId, dateString };
}

}

module.exports = ParameterParser;

I am testing it using Mocha, Chai, Chai-as-Promised and Sinon:

'use strict';

const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const sinon = require('sinon');

const parameterParser = require('../../src/core/ParameterParser.js');
const sqlFileReader = require('../../src/database/SqlFileReader.js');
const Lnfe = require('../../src/errors/LoanNotFoundError');

chai.use(chaiAsPromised);
const { expect } = chai;

const retData = {
rowsCount: 1,
rows: [{ client_id: 872 }],
};

const reqDateAndLoan = {
query: {
    plaint_init_date: '2022-03-15',
    loan_id: '1773266',
},
};

const reqDateAndClient = {
query: {
    plaint_init_date: '2022-03-15',
    client_id: '872',
},
};

const reqDateAndLoanIdThatDoesNotExist = {
query: {
    plaint_init_date: '2022-03-15',
    loan_id: '1773266999999999999',
},
};

describe('prepareInputParameters', () => {

sinon.stub(sqlFileReader, 'read').returns({ retData });

it('results in correct client id and date string', async () => {
    const ret = { clientId: 872, dateString: '2016-03-15' };
    expect(await parameterParser.prepareInputParameters(null, reqDateAndLoan)).to.deep.equal(ret);
});

it('results in a client id equal to the that input if the request query contains a client id', async () => {
    const ret = { clientId: '872', dateString: '2016-03-15' };
    expect(await parameterParser.prepareInputParameters(null, reqDateAndClient)).to.deep.equal(ret);
});

it('throws a \'Loan Not Found\' error', async () => {
    expect(parameterParser.prepareInputParameters(null, reqDateAndLoanIdThatDoesNotExist)).eventually.throw(Lnfe, 400, 'Loan Not Found');
});

it('DOES NOT throw a \'Loan Not Found\' error', async () => {
    expect(async () => {
        await parameterParser.prepareInputParameters(null, reqDateAndLoanIdThatDoesNotExist);
    }).to.not.throw(Lnfe, 400, 'Loan Not Found');
});


});

The tests pass but the output has an couple of node warnings:

prepareInputParameters
✓ results in correct client id and date string
✓ results in a client id equal to the that input if the request query contains a client id
✓ throws a 'Loan Not Found' error
(node:23875) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): AssertionError: Loan Not Found: expected { Object (clientId, dateString) } to be a function
(node:23875) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
✓ DOES NOT throw a 'Loan Not Found' error


4 passing (19ms)

Any ideas how I can get rid of these warnings or what I'm doing wrong?

Share Improve this question asked Mar 26, 2018 at 18:33 Dave ChambersDave Chambers 2,5632 gold badges35 silver badges56 bronze badges 7
  • You need to call the function catch for every promise execution. For example: await parameterParser.prepareInputParameters(null, reqDateAndLoan).catch(err => console.log(err)) – Ele Commented Mar 26, 2018 at 18:37
  • @Ele changing my code to expect(parameterParser.prepareInputParameters(null, reqDateAndLoanIdThatDoesNotExist)).catch(err => console.log(err)).eventually.throw(Lnfe, 400, 'Loan Not Found'); results in the error: Error: Invalid Chai property: catch. Did you mean "match"? – Dave Chambers Commented Mar 26, 2018 at 18:47
  • 1 you are adding catch to the wrong function object – 0.sh Commented Mar 26, 2018 at 18:48
  • @0.sh has explained it :) – Ele Commented Mar 26, 2018 at 18:49
  • So what should that line of code be instead of expect(parameterParser.prepareInputParameters(null, reqDateAndLoanIdThatDoesNotExist)).eventually.throw(Lnfe, 400, 'Loan Not Found'); please? – Dave Chambers Commented Mar 26, 2018 at 18:51
 |  Show 2 more ments

2 Answers 2

Reset to default 3

Some ideas to help you understand the different stages of the promise that I piled (the example, ie) with a ES6 class:

// asyncpromiserejection.js

class asyncpromise{ 
    constructor(s){
        this.s=s
    }
PTest(){    
    var somevar = false;
    somevar=this.s;
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
 //       else
   //         reject();
    });
}
}
module.exports=asyncpromise

With the else part mented, the promise would either resolve if true is passed to the class or the test would timeout because the promise does not know what to do when the value is false.

// test.js

const asyncpromise=require('./asyncpromiserejection.js')
describe("asyncTests", () => {
it("handles Promise rejection",async ()=>{
    var t=new asyncpromise(false)
    await t.PTest().then(function () {
     console.log("Promise Resolved");
})
})        
});

Fig 1.0

Unment the else part and you will get the same error but with the warning that promise rejection has been deprecated - Fig 1.1 - because now, although the promise rejection due to the falsey value is handled in the code, the test ie., the calling method, has not handled it.

class asyncpromise{ 
    constructor(s){
        this.s=s
    }
PTest(){    
    var somevar = false;
    somevar=this.s;
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
}
module.exports=asyncpromise

Fig 1.1

Now, handle the promise rejection in the test like so:

const asyncpromise=require('./asyncpromiserejection.js')
describe("asyncTests", () => {
it("handles Promise rejection",async ()=>{
    var t=new asyncpromise(false)
    await t.PTest().then(function () {
     console.log("Promise Resolved");
}).catch(()=>{console.log("Promise rejcted")})
})        
});

And, you can pass some custom message in the reject part of the promise to assert in a test like so:

const assert=require('chai').assert
const asyncpromise=require('./asyncpromiserejection.js')
describe("asyncTests", () => {
it("handles Promise rejection",async ()=>{
    var t=new asyncpromise(false)
    await t.PTest().then(function () {
     console.log("Promise Resolved");
}).catch((error)=>{
    console.log("Promise rejected")
    assert.equal(error.message,"Promise rejected")
})
})        
});

// asyncpromiserejection.js

class asyncpromise{ 
    constructor(s){
        this.s=s
    }
PTest(){    
    var somevar = false;
    somevar=this.s;
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
           throw new Error("Promise rejcted")
            //reject();
    });
}
}
module.exports=asyncpromise

I use to catch unhandled rejection using

process.on('unhandledRejection', (err, p) => {
  console.error('unhandledRejection', err.stack, p)
})

so I have the trace and I can locate and fix

for DeprecationWarning should work this - I'm not sure, but accordingly with documentation https://nodejs/api/process.html#process_event_warning

process.on('warning', (warning) => {
  console.warn(warning.name);
  console.warn(warning.message);
  console.warn(warning.stack);
});
发布评论

评论列表(0)

  1. 暂无评论