How to stub the same method in two test-cases using Sinon? - node.js

I am using Node, Mongoose, Sinon, Mocha.
In the DAO layer, I have methods named methodA, methodB. In the service layer, I have servMethodA (calls methodA), servMethodB (calls methodB), servMethodC. Now, servMethodC calls the methodA from DAO and then I have a call to methodB nested in it.
In the test cases for the service layer, I have already stubbed methodA and methodB. How do I stub them again for the test-case for servMethodC?
These are my service methods.
function findLikeByPostIdAndUserId(postId, userId) {
return new Promises((resolve, reject) => {
likeDislikeDao.findLikeByPostIdAndUserId(postId, userId).
then((data) => {
resolve(data);
})
.catch((error) => {
reject(error);
});
});
}
function findDislikeByPostIdAndUserId(postId, userId) {
return new Promises((resolve, reject) => {
likeDislikeDao.findDislikeByPostIdAndUserId(postId, userId).
then((data) => {
resolve(data);
})
.catch((error) => {
reject(error);
});
});
}
function saveLike(like) {
console.log(like);
return new Promises((resolve, reject) => {
console.log(data);
likeDislikeDao.findLikeByPostIdAndUserId(like.postId, like.userId).
then((data) => {
if (!data) {
likeDislikeDao.findDislikeByPostIdAndUserId(like.postId, like.userId).
then((dislikeData) => {
if (!dislikeData) {
likeDislikeDao.saveLike(like).
then((data) => {
resolve(data);
});
}
else {
likeDislikeDao.deleteDislike(dislikeData._id)
.then((data) => {
likeDislikeDao.saveLike(like).
then((data) => {
resolve(data);
});
});
}
});
}
else {
likeDislikeDao.deleteLike(data._id)
.then((data) => {
//likeDislikeDao.saveLike(like).
// then((data) => {
// resolve(data);
// });
resolve(data);
});
}
})
.catch((error) => {
reject(error);
});;
});
}
Here are my individual test cases.
describe('saveLike', function () {
it('should add a like', function () {
var stub = sinontwo.stub(likeDislikeDao, 'saveLike');
stub.withArgs(newLike).callsFake(() => {
return Promise.resolve(newLike);
});
var stubtwo = sinontwo.stub(likeDislikeDao, 'saveDislike');
stubtwo.withArgs(newDislike).callsFake(() => {
return Promise.resolve(newDislike);
});
const stubthree = sinontwo.stub(likeDislikeDao, 'findLikeByPostIdAndUserId');
stubthree.callsFake(() => {
return Promise.resolve(like);
});
const stubfour = sinontwo.stub(likeDislikeDao, 'findDislikeByPostIdAndUserId');
stubfour.callsFake(() => {
return Promise.resolve(dislike);
});
likeDislikeService.saveLike(newLike).then(response => {
console.log('1 -> ');
console.log(response);
assert.length(response, 1);
});
stub.withArgs(like).callsFake(() => {
return Promise.reject('');
});
stubtwo.withArgs(dislike).callsFake(() => {
return Promise.reject('');
});
likeDislikeService.saveLike(like).then(response => {
console.log('2 -> ');
console.log(response);
assert.lengthOf(response, 1);
}).then((err) => {
console.log(err);
assert.isDefined(err);
});
});
});
describe('findLikeByPostIdAndUserId()', function () {
it('should find likes by post id and user id', function () {
likeDislikeService.findLikeByPostIdAndUserId(1,2).then(response => {
assert.length(response, 1);
});
likeDislikeService.findLikeByPostIdAndUserId(1,2).then(response => {
assert.length(response, 1);
}).catch((err) => {
//console.log(err);
assert.isDefined(err);
});
})
});
describe('findDislikeByPostIdAndUserId()', function () {
it('should find dislikes by post id and user id', function () {
likeDislikeService.findDislikeByPostIdAndUserId(1,2).then(response => {
assert.length(response, 1);
});
likeDislikeService.findDislikeByPostIdAndUserId(1,2).then(response => {
assert.length(response, 1);
}).catch((err) => {
console.log(err);
assert.isDefined(err);
});
})
});
Problem is, I am not getting the "reject" part of the find-methods in the coverage. Also, the saveLike method is not being covered properly apart from the 'then' lines.

Related

How do you update a thumbnailPhoto in Active Directory using NodeJS and ldapjs?

I'm new to working with Active Directory in general. I'm trying to update the thumbnailPhoto attribute using ldapjs npm package I have my code setup to be able to update attributes in general and it works well.
I get my user like so:
const customeParser = function(entry, raw, callback){ if (raw.hasOwnProperty("thumbnailPhoto")){ entry.thumbnailPhoto = raw.thumbnailPhoto; } callback(entry) }
find(filter, cb) {
const client = ldap.createClient(this.ldapOptions)
client.on('error', err => {
console.error(err.message)
})
//Serach for users
client.bind(
this.options.dn,
this.options.password,
(err) => {
if (err) {
console.error((new Date).toUTCString(), 'Initial Bind Error', err)
client.unbind(() => {
client.destroy()
cb(err)
})
} else {
client.search(
'DC=foo,DC=local', {
scope: 'sub',
attributes: [
'distinguishedName',
'name',
'sn',
'givenName',
'mail',
'sAMAccountName',
'telephoneNumber',
'thumbnailPhoto',
// 'photoURL',
// 'profileImage',
'extensionAttribute1',
'msExchExtensionCustomAttribute1'
],
entryParser: customeParser,
filter: `${filter}`
},
(err, ee) => {
if (err) {
console.log((new Date).toUTCString(), 'SEARCH RESULT', err)
client.unbind(() => {
client.destroy()
cb(err)
})
}
ee.on('searchEntry', (entry) => {
ee.on('end', () => {
client.unbind(() => {
client.destroy()
cb(null, entry.object)
})
})
});
});
}
});
}
I call my modifyUser method from my LDAP class like so:
let changes = {
thumbnailPhoto: 'http://<ip>:<port>/img/photo.jpg'
}
ad.modifyUser(user.dn, changes, function (err, mod) {
if (err) {
console.log('ERROR: ' + JSON.stringify(err));
return;
}
if (!mod) {
console.log('Search: ' + mod + ' not found.');
} else {
console.log('MOD: ', JSON.stringify(mod));
}
})
modifyUser:
modifyUser(user, attributes, cb) {
const client = ldap.createClient(this.ldapOptions)
client.on('error', err => {
console.error(err.message)
})
//Serach for users
client.bind(
this.options.dn,
this.options.password,
(err) => {
if (err) {
console.error((new Date).toUTCString(), 'Initial Bind Error', err)
client.unbind(() => {
client.destroy()
cb(err)
})
} else {
var change = new ldap.Change({
operation: 'replace',
modification: attributes
});
console.log('CHANGE: ', attributes)
client.modify(user, change, function(err) {
if(err) console.error('ERROR: ', err);
},
(err, ee) => {
if (err) {
console.log((new Date).toUTCString(), 'SEARCH RESULT', err)
client.unbind(() => {
client.destroy()
cb(err)
})
}
ee.on('searchEntry', (entry) => {
ee.on('end', () => {
client.unbind(() => {
client.destroy()
cb(null, entry.object)
})
})
});
});
}
});
}
When I update the photo using my LDAP Tool it converts it to what i believe to be an octet or some sort of hex value. How do i mimic that in nodejs?
Am I on the right track? All other attributes get updated instantly using the code above, but the image fails to update...
Also is there a way to update multiple attributes at once? I get the error that only one attribute can be modified at a time.
Thanks in advance for your time!

How to stub Mongoose methods with Sinon to test DAO?

Here is my Node unit test-case for a DAO method that returns a list of Category objects. Category is the name of my model. However, when I run this code, it is getting stuck.
describe('findAllCategories', function () {
it('should find all categoriess', function () {
var stub = sinon.stub(Category, 'find');
stub.callsFake(() => {
return Promise.resolve(allCat);
});
categoryDao.findAllCategories().then(response => {
assert.lengthOf(response, 1);
})
.catch((error) => {
console.log(error);
assert.isDefined(error);
});
stub.callsFake(() => {
return Promise.reject('');
});
categoryDao.findAllCategories().then(response => {
assert.lengthOf(response, 1);
}).catch((err) => {
console.log(err);
assert.isDefined(err);
});
});
});
Any way around?

"n" number of API calls in the sequentially order in the Node.js?

How to call "n" number of API calls in the sequentially order(each API response as input parameter for next API call) in the Node.js?
Please, review below example of promise in which you may find that it will execute synchronously as your requirement.
let firstPromise = (() => {
return new Promise((resolve) => {
resolve("first promise");
});
});
let secondPromise = (() => {
return new Promise((resolve) => {
resolve("second promise");
});
});
let thirdPromise = (() => {
return new Promise((resolve) => {
resolve("third promise");
});
});
let fourthPromise = (() => {
return new Promise((resolve) => {
resolve("fourth promise");
});
});
firstPromise()
.then((res) => {
console.log(res);
return secondPromise();
})
.then((res) => {
console.log(res);
return thirdPromise();
})
.then((res) => {
console.log(res);
return fourthPromise();
})
.then((res) => {
console.log(res);
})
.catch((err)=>{
throw new Error(err);
});

amqplib nodejs to consume rabbitmq

this is how i consume the queue in rabbit, i wonder why this promise still hangs and return no result. i am trying to hit an endpoint that call this promise and expect it to return just ok to make sure it gives me a 200 OK status. now it acts like it somehow does not get any return from this service, i wonder what i did wrong. thanks
return new Promise((resolve,reject) => {
try{
rabbit.then(conn => {
return conn.createChannel();
})
.then(ch => {
let shit = ch.assertQueue(USER_LOG_QUEUE)
.then(ok => {
if(ok.messageCount > 0){
return ch.consume(USER_LOG_QUEUE, function(msg) {
if (msg !== null) {
ch.ack(msg);
writeToFile(msg.content.toString())
.then(rs => {
console.log(rs);
})
.catch(err => reject(err));
}
console.log('finished');
ch.close();
resolve(ok);
})
}else{
console.log('empty list : finished');
ch.close();
resolve(ok);
}
})
.then(ok => {
console.log('empty list2 : finished');
resolve(ok)
})
.catch(err => reject(err));
}catch(err){
reject(err);
}
});

how to bypass multiple then in of mongoose

I Don't want to make checks as if (!isPresent) then do this ....
Is their any way to bypass all the then when my work is complete
var isPresent=false;
myPromise
.then((employee) => {
if (employee) {
// throw 'employee already exist';
isPresent = true;
return res.data(mapper.toFullModel(employee));
}
return model;
});
.then(model => {
if (!isPresent) {
return new db.employee(model).save();
}
})
.then(employee => {
if (!isPresent) {
employee.token = auth.getToken(employee);
return employee.save();
}
})
.then(employee => {
if (!isPresent) {
res.data(mapper.toFullModel(employee));
}
})
.catch(err => {
res.failure(err);
});
You can rewrite your promise chain so the second part of it gets nested:
myPromise.then(employee => {
if (employee) {
return res.data(mapper.toFullModel(employee));
}
return new db.employee(model).save().then(employee => {
employee.token = auth.getToken(employee);
return employee.save();
}).then(employee => {
return res.data(mapper.toFullModel(employee));
});
}).catch(err => {
res.failure(err);
});

Resources