Timing issue while writing mocha test cases - javascript

I am trying to write a test case for one of my REST Apis using mocha.
My Rest api looks like this:
server.route({
method : "DELETE",
path : "/local/{id}",
handler: function (request, reply) {
var id = request.params.id;
return getId(id)
.then(function (result) {
return testFunction(result, id, reply);
})
.catch (function (err) {
reply(400).err;
})
}
function testFunction(result, id, reply) {
return update(id, result)
.then(function (resp) {
reply(resp);
stopSomething(id)
.then(function () {
//do some work
return Bluebird.resolve(data);
})
.catch(function (error) {
//handle error & just log..user does not need to know
//stopSomething is a promise chain which runs in background
});
})
.catch(function (err) {
//handle error and reply to user
});
}
});
To test this I wrote the following test case:
describe("with an valid id", function () {
var stopSomethingStub;
var result
before(function () {
stopSomethingStub = Sinon.stub(stopSomethinbObject, "stopSomething", function () {
return Bluebird.resolve();
});
return new Request("DELETE", "/local/id123").inject(server)
.then(function (data) {
result = data;
});
});
after(function () {
//do clean up of stubs
});
it("deletes id", function () {
expect(result.statusCode).to.equal(200);
expect(stopSomethingStub.called).to.be.true;
//Few more checks
});
}
Right now, the "it" block executes immediately after receiving the 200 Ok response for the DELETE Request. However I would like it to finish the entire promise chain before checking the assertion. stopSOmethingStub.called is shown as false if I keep it as the first expect block. However if I keep it as the last assertion it works. I think this is some timing issue.

Related

test promise reject case using mocha

I want to make test case for promise reject case.
Here is my code
1) File: TemplateFinder.js
**I want to make test for this method on promise reject using *mocha* how can i achieve this?**
var findTemplate = function (template) {
return templateFinder.find(templateName)
.then( (result) => {
return result.id;
});
};
2) query.js
var find = function (template) {
return knex.where({
internal_name: template,
})
.select('external_id')
.from('mailing_external_template')
.then(function (data) {
if (0 === data.length) {
return Promise.reject(RangeError('no result for id'));
} else {
return data[0].external_id;
}
});
};
3) app.js
Main file to run
function findTemplate()
{
templateFinder.findGoodTemplate('good-mail-template');
}
initiateProcess()
.then(function (fromResolve) {
return findTemplate();
})
.catch(function (e) {
});
My try:
it('should throw error if template not found', function () {
var findTemplateIdStub = sinon.stub(templateFinder, 'find');
var error = 'my expected error message returned by my function';
findTemplateIdStub.returns(Promise.reject(error));
return templateFinder.findTemplate(templateName)
.catch(function(err) {
assert.equal(err, error);
});
});
the problem with my try is findTemplate has no catch so how can i am asserting variables from my test case, not original. (Catch is not in code but still my test pass.) Please help me to make test case for findTemplate reject case.
Is findTemplateIdStubsupposed to return a promise?
If that's the case, you can include sinon-as-promised and the stub should be:
findTemplateIdStub.rejects('some error') for the bad case
findTemplateIdStub.resolves(1234) for the good case

how should i do asynchronous unit testing?

I am using pg-promise. i am learnner please excuse if it seems trivial to you. how can i wrtie unit test for. it errors out data is undefined. i have been making connection in js file and export that module.another js file use to query against database and fetch result set. code is working as expected having issue how can i write unit test with mocha and chai.
test1.js
var dbConn= pgp(connUrl);
module.exports = {
getconnect: function () {
return dbConn;
}
};
test2.js
module.exports = {
getData: function (req, res) {
db.getconnect().query(sqlStr, true)
.then(function (data) {
console.log("DATA:", data);
return data;
} } }
unittest.js
describe("Test Cases", function (done) {
it('retrieve response', function (done) {
var req = {};
var res = {};
test2.getData(req, res);
// how would i retrieve value of data from test2.js so i can test
done();
});
});
how would i retrieve "data" value from test2.js inthe unittest.js
Your getData must return the promise. Client code will be able to recognize the moment it's finished(resolved).
module.exports = {
getData: function (req, res) {
return db.getconnect().query(sqlStr, true)
.then(function (data) {
console.log("DATA:", data);
return data;
} } }
test:
describe("Test Cases", function () {
it('retrieve response', function (done) {
var req = {};
var res = {};
test2.getData(req, res).then(function(data){
// test of data returned
done(); // finish test
}).catch(done);// report about error happened
});
});
If you don't need to any process of data in your module, you can to remove whole .then section without any functionality changes.
But if you want to preprocess data - don't forget to return it from each chained .then.
If your test library requires stubs for async stuff, you can use async/await feature to deal with it.
it('retrieve response', async function(){
try {
var data = await test2.getData(req, res);
// test data here
} catch (e) {
// trigger test failed here
}
});
Or stub it, something like this:
var dbStub = sinon.stub(db, 'getConnect');
dbStub.yields(null, {query: function(){/*...*/}});
If you have a function returning promise then you can use await in your tests:
describe("Test Cases", function (done) {
it('retrieve response', async function (done) {
try {
var data = await test2.getData();
// check data constraints ...
...
} catch(err) {
...
}
done(); // finish test
});
});

How to properly chain Promises with nesting

My node project currently contains a sideway christmas tree of nested callbacks in order to fetch data and process them in the right order. Now I'm trying refactor that using Promises, but I'm unsure how to do it properly.
Let's say I'm fetching a list of offices, then for each office all their employees and then each employees' salary. In the end all entities (offices, employees and salaries) should be linked together and stored in a database.
Some pseudo-code illustrating my current code (error handling omitted):
fetch(officesEndpoint, function (data, response) {
parse(data, function (err, offices) {
offices.forEach(function (office) {
save(office);
fetch(employeesEndPoint, function (data, response) {
parse(data, function (err, employees) {
// link each employee to office
save(office);
save(employee);
employees.forEach(function () {
fetch(salaryEndpoint, function (data, response) {
parse(data, function (err, salaries) {
// link salary to employee
save(employee);
});
});
});
});
});
});
});
});
I tried solving this with promises, but I have a couple of problems:
kind of verbose?
each office needs to be linked to their respective employees, but in the saveEmployees function I only have access to the employees, not the office from further up in the chain:
var restClient = require('node-rest-client');
var client = new restClient.Client();
var xml2js = require('xml2js');
// some imaginary endpoints
var officesEndpoint = 'http://api/offices';
var employeesEndpoint = 'http://api/offices/employees';
var salaryEndpoint = 'http://api/employees/:id/salary';
function fetch (url) {
return new Promise(function (resolve, reject) {
client.get(url, function (data, response) {
if (response.statusCode !== 200) {
reject(statusCode);
}
resolve(data);
});
});
}
function parse (data) {
return new Promise(function (resolve, reject) {
xml2js.parseString(data, function (err, result) {
if (err) {
reject(err);
}
resolve(result);
});
});
}
function saveOffices (offices) {
var saveOffice = function (office) {
return new Promise(function (resolve, reject) {
setTimeout(function () { // simulating async save()
console.log('saved office in mongodb');
resolve(office);
}, 500);
})
}
return Promise.all(offices.map(saveOffice));
}
function saveEmployees (employees) {
var saveEmployee = function (employee) {
return new Promise(function (resolve, reject) {
setTimeout(function () { // simulating async save()
console.log('saved employee in mongodb');
resolve(office);
}, 500);
})
}
return Promise.all(offices.map(saveEmployee));
}
fetch(officesEndpoint)
.then(parse)
.then(saveOffices)
.then(function (savedOffices) {
console.log('all offices saved!', savedOffices);
return savedOffices;
})
.then(function (savedOffices) {
fetch(employeesEndPoint)
.then(parse)
.then(saveEmployees)
.then(function (savedEmployees) {
// repeat the chain for fetching salaries?
})
})
.catch(function (error) {
console.log('something went wrong:', error);
});
You don't necesseraly have to nest, this would work too:
fetch(officesEndpoint)
.then(parse)
.then(saveOffices)
.then(function(savedOffices) {
console.log('all offices saved!', savedOffices);
return savedOffices;
})
.then(function(savedOffices) {
// return a promise
return fetch(employeesEndPoint); // the returned promise can be more complex, like a Promise.all of fetchEmployeesOfThisOffice(officeId)
})
// so you can chain at this level
.then(parse)
.then(saveEmployees)
.then(function(savedEmployees) {
return fetch(salariesEndPoint);
})
.catch(function(error) {
console.log('something went wrong:', error);
});
Your promisified functions fetch, parse, saveOffices and saveEmployees are fine. With those, you can refactor your current code to use promises, chain instead of nest where applicable, and leave out a bunch of error handling boilerplate:
fetch(officesEndpoint)
.then(parse)
.then(function(offices) {
return Promise.all(offices.map(function(office) {
return save(office)
.then(function(){ return fetch(employeesEndPoint); })
.then(parse)
.then(function(employees) {
// link each employee to office
// throw in a Promise.all([save(office), save(employee)]) if needed here
return Promise.all(employees.map(function(employee) {
return fetch(salaryEndpoint)
.then(parse)
.then(function(salaries) {
return Promise.all(salaries.map(function(salary) {
// link salary to employee
return save(employee);
}));
});
}));
});
}));
});
In the innermost loop callback, you've got all of office, employee and salary available to interlink them to your liking. You cannot really avoid this kind of nesting.
You'll get back a promise for a huge array of arrays of arrays of save results, or for any error in the whole process.
It is good approach to change this
if (response.statusCode !== 200) {
reject(statusCode);
}
resolve(data);
to this
if (response.statusCode !== 200) {
return reject(statusCode);
}
resolve(data);
In your example, the result will be same, but if you are making more things (like doing something in database) the unexpected result may occure, because without return the whole method will be executed.
This example
var prom = new Promise((resolve,reject) => {
reject(new Error('error'));
console.log('What? It did not end');
resolve('Ok, promise will not be called twice');
});
prom.then(val => {
console.log(val);
}).catch(err => {
console.log(err.message);
});
is having this output
What? It did not end
error
To the question - if you need access to more than one returned value (i.e. offices AND employies), you have basically two options :
Nested promises - this is not generally bad, if it "makes sense". Altought promises are great to avoid huge callback nesting, it is ok to nest the promises, if the logic needs it.
Having "global" variables - you can define variable in the scope of the promise itself and save results to it, therefore the promises are using these variables as "global" (in their scope).

Angularjs promise object testing

I'm newbie about angular testing and I'm challenging this scenario.
This function (not written by me) return a promise object:
GetByEmail: function (email) {
var def = $q.defer();
this.InvokeMyApi(
this.ApiParams.EntryPoints.Account.Mode,
this.ApiParams.EntryPoints.Account.GetState,
{},
{ Email: email }).then(
function (e) {
def.resolve(e.data);
}, function (e) {
def.reject(e);
});
return def.promise;
}
My goal is to test it with Qunit so I'm trying to read the promise content with this one:
var promise = GetByEmail(email);
promise.then(function (data) {
console.log('successo ', data);
}, function (error) {
console.log('errore ', error);
});
It seems so simple but nothing happens when I try to run the second function.
Any help for me?

How do I use mocha to do asynchronous tests using 'done();'?

I'm working on trying to write an asynchronous test with mocha using the done(); call. This is my code so far.
it('should have data.', function () {
db.put(collection, key, json_payload)
.then(function (result) {
result.should.exist;
done();
})
.fail(function (err) {
err.should.not.exist;
done();
})
})
The result however is that the code just executes without waiting for the then or fail to actually return with a result. Does done(); need to be at a different place within the code?
Also posted the whole repo right here: https://github.com/Adron/node_testing_testing
if you want an async test you need to handle the done parameter
it('should have data.', function (done) {
db.put(collection, key, json_payload)
.then(function (result) {
result.should.exist;
done();
})
.fail(function (err) {
err.should.not.exist;
done();
})
})
also if you are using Q as your promise library you might want to complete your chain like so.
it('should have data.', function (done) {
db.put(collection, key, json_payload)
.then(function (result) {
result.should.exist;
})
.fail(function (err) {
err.should.not.exist;
})
.done(done,done)
})
I think you mean to actually call the done() callback.
it('should have data.', function () {
db.put(collection, key, json_payload)
.then(function (result) {
result.should.exist;
done();
})
.fail(function (err) {
err.should.not.exist;
done();
})
})

Categories

Resources