Object [object Object] has no method 'test' - node.js

I am trying to use a function in another module i am not able to use it may i know what is the issue?
this.test = function(callback) {
callback('i am test');
};
module.exports.config = function (settings, callback) {
this.test(function(err,res){
console.log(res);
});
};

The value of this is different because you're inside another function. Try this instead:
this.test = function(callback) {
callback('i am test');
};
var self = this;
module.exports.config = function (settings, callback) {
self.test(function(err,res){
console.log(res);
});
};
Or just give the function name and call it directly:
function test(callback) {
callback('i am test');
};
module.exports.config = function (settings, callback) {
test(function(err,res){
console.log(res);
});
};

Related

How to unit test nested function in node js?

I have a function for which I am writing unit test but that function is calling another function and there I am not able to mock/stub that function.
for example :
function getValue( param1, param2, callback){
getData(param1, param3).then( response) => {
return callback();
}, (err) => {
return callback();
});
}
So I don't know how to mock getData() function.
Here is a working example that demonstrates what you are trying to do:
lib.js
function getData(param1, param2) {
return fetch('someUrl'); // <= something that returns a Promise
}
exports.getData = getData;
code.js
const lib = require('./lib');
export function getValue(param1, param2, callback) {
return lib.getData(param1, param2).then(response => {
callback(response);
}).catch(err => {
callback(err);
});
}
exports.getValue = getValue;
code.test.js
const sinon = require('sinon');
const lib = require('./lib');
const { getValue } = require('./code');
describe('getValue', () => {
it('should do something', async () => {
const stub = sinon.stub(lib, 'getData');
stub.resolves('mocked response');
const callback = sinon.spy();
await getValue('val1', 'val2', callback);
sinon.assert.calledWithExactly(stub, 'val1', 'val2'); // Success!
sinon.assert.calledWithExactly(callback, 'mocked response'); // Success!
});
});
Update
OP added in the comments that they can't use async / await and are exporting the function using module.exports = getData;.
In that case the module export is the function and the entire module needs to be mocked with something like proxyquire.
The assertions should be done in a then callback and the test should return the resulting Promise so mocha knows to wait for it to resolve.
Updated example:
lib.js
function getData(param1, param2) {
return fetch('someUrl'); // <= something that returns a Promise
}
module.exports = getData;
code.js
const getData = require('./lib');
function getValue(param1, param2, callback) {
return getData(param1, param2).then(response => {
callback(response);
}).catch(err => {
callback(err);
});
}
module.exports = getValue;
code.test.js
const sinon = require('sinon');
const proxyquire = require('proxyquire');
describe('getValue', () => {
it('should do something', () => {
const stub = sinon.stub();
stub.resolves('mocked response');
const getValue = proxyquire('./code', { './lib': stub });
const callback = sinon.spy();
return getValue('val1', 'val2', callback).then(() => {
sinon.assert.calledWithExactly(stub, 'val1', 'val2'); // Success!
sinon.assert.calledWithExactly(callback, 'mocked response'); // Success!
});
});
});
function getValue( param1, param2, callback){
getData(param1, param3).then( response) => {
callback(response);
});
}
getvalue(param1, param2, function(error, response)) {
console.log(response)
}
It might help you.

Function enters then before request completed

My async function enters then before request is completed. Shouldn't Then part of the code executes only after the async function is completed? How to make the function call only when all the function has finished executing?
app.js
var request_test = require('./request_test');
baseUrl = "https://github.com";
promiseFunction().then((result)=>{
console.log("complete")
});
var promiseFunction = async function promiseFunction() {
request_test.request_test(baseUrl);
}
request_test.js
var request = require('request');
var cheerio = require('cheerio');
var request_test = function check(baseUrl) {
console.log("baseUrl:" + baseUrl)
var options = {
url: baseUrl
};
request(options, function (error, response, html) {
if (!error) {
console.log("no error");
}else{
console.log("else js");
console.log(error);
}
});
}
module.exports = {
request_test: request_test
};
In order to use then() you need to return a promise. So here is an example of the good old style promise chain, simply return promise from request_test and once you resolve or reject it, then() will be called:
promiseFunction().then((result) => {
console.log("complete");
});
function promiseFunction() {
return request_test();
}
function request_test() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("no error");
resolve();
}, 1000);
});
}
Or maybe use the modern approach - async method to await call function that returns promise.
promiseFunction();
async function promiseFunction() {
await request_test();
console.log('complete');
}
function request_test() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("no error");
resolve();
}, 1000);
});
}
Your issue is coming from var request_test = function check(baseUrl) { ... inside this function you are not returning promise, you are even returning nothing :)
if you are using async I would go ahead and use the await/async syntax. Also the package request does not return a promise, you have an alternative with request-promise-native. The promise should be the return value of your helper function. It could look like this:
var request_test = require('./request_test');
var baseUrl = "https://github.com";
var promiseFunction = async function () {
var result = await request_test.request_test(baseUrl);
console.log("complete");
}
promiseFunction();
and the module:
var request = require('request-promise-native');
var cheerio = require('cheerio');
var request_test = function check(baseUrl) {
console.log("baseUrl:" + baseUrl)
var options = {
url: baseUrl
};
return request(options).then(function (error, response, html) {
if (!error) {
console.log("no error");
} else{
console.log("else js");
console.log(error);
}
});
}
module.exports = {
request_test: request_test
};

How to pass value between Async.series functions without global variable

var Async = require('async');
var Test_Hander = function () {
};
Test_Hander.prototype.begin = function () {
Async.series([
this.first, // this.first.bind(this) does not work either
this.second
],function (error) {
if (error) {
// shit
}
else {
// good
}
});
};
Test_Hander.prototype.first = function (callback) {
console.log('Enter first function');
callback(null,'I am from first function');
};
Test_Hander.prototype.second = function (one, callback) {
console.log('Enter second function');
console.log('parameter one: ');
console.log(one);
console.log(callback);
callback(null);
};
var hander = new Test_Hander();
hander.begin();
I want to pass some value from function first to function second. And I know that waterfall and global variable are both ok. However, can I just pass a result value from function first to function second without using waterfall and global variable?
Using promise you can chain the methods and execute the code similar to async.series and you don't need to require a async module.
var Test_Hander = function () {
};
Test_Hander.prototype.begin = function () {
this.first()
.then(this.second)
.catch(function(err){
// Handle error
});
};
Test_Hander.prototype.first = function (callback) {
return new Promise(function(reject, resolve){
// do something
// if err : reject(err)
// else : resolve(data);
});
};
Test_Hander.prototype.second = function (responsefromFirst) {
// Do somethign with response
};
var hander = new Test_Hander();
hander.begin();

Chaining multiple chained promises with Q (loopback app)

Here is a scenario, I've implemented a loopback remote method which imports some data from REST connector to local postgresql connector.
I can do this for a single model
var importData = function (model, cb) {
migrateModel(model, cb)
.then(findImportInfo)
.then(fetchRemoteData)
.then(processFetchedData)
.then(updateImportInfo)
.then(countLocalData)
.then(importCompleted)
.catch(function (err) {
importFailed(err, cb);
})
.done(function () {
console.log('done');
});
};
So the chain does many thing and at the end importCompleted calls the provide cb which is the callback that returns the response to the REST API.
But I can't figure how to do this with multiple models and return each result. I tried something like this, it works actually but REST API never receives a result.
var importDataAll = function (app, cb) {
var models = app.models();
var deferred = Q.defer();
var promises = [];
var results = [];
function doCallback() {
cb(null, results);
}
models.forEach(function (model) {
if (typeof model.importData === 'function') {
migrateModel(model, model.definition.name, null)
.then(findImportInfo)
.then(fetchRemoteData)
.then(processFetchedData)
.then(updateImportInfo)
.then(countLocalData)
.then(function (prevResult) {
var deferred = Q.defer();
var remoteCount = prevResult.dataCount;
var localCount = prevResult.recordCount;
var result =
{
'time': new Date(),
'remoteCount': remoteCount,
'localCount': localCount,
'started': prevResult.started,
'completed': new Date()
}
results.push(result);
deferred.resolve(result);
return deferred.promise;
})
.catch(function (err) {
promises.reject(err);
})
}
});
return Q.allSettled(promises).then(doCallback);
};
I'm lost at that point, any ideas?
EDIT
Trying #Otze's answer I tried this also
var importDataAll = function (app, cb) {
var models = app.models().filter(function (element, index, array) {
return typeof element.importData === 'function';
});
var promises = models.map(function (model) {
migrateModel(model, model.definition.name, null)
.then(findImportInfo)
.then(fetchRemoteData)
.then(processFetchedData)
.then(updateImportInfo)
.then(countLocalData)
.then(importResult)
.catch(function (err) {
promises.reject(err);
})
});
Q.all(promises)
.then(function (resolvedPromises) {
cb(null, results);
});
};
But the result is the same, cb gets called early but the code actually runs in order. I just can't get the result to the response. I think it's never ends so the REST API gets no content after some time.
Have a look at Q.all or any of the other promise combination functions:
http://documentup.com/kriskowal/q/#combination
With Q.all you could do somehting like this:
var promises = myModels.map(doAllThePromiseThings);
Q.all(promises)
.then(function(resolvedPromises) {
doStuff();
});
Note that you need to return a promise from doAllThePromiseThings.
Since .then returns a promise you can simply do:
.then(function (prevResult) {
return {
'time': new Date(),
'remoteCount': prevResult.dataCount,
'localCount': prevResult.recordCount,
'started': prevResult.started,
'completed': new Date()
};
})
instead of
.then(function (prevResult) {
var deferred = Q.defer();
var remoteCount = prevResult.dataCount;
var localCount = prevResult.recordCount;
var result =
{
'time': new Date(),
'remoteCount': remoteCount,
'localCount': localCount,
'started': prevResult.started,
'completed': new Date()
}
results.push(result);
deferred.resolve(result);
return deferred.promise;
})
I use bluebird library's map method to accomplish such use cases:
https://github.com/petkaantonov/bluebird/blob/master/API.md#mapfunction-mapper--object-options---promise
var Promise = require('bluebird');
var importDataAll = function (app, cb) {
var models = app.models().filter(function (element, index, array) {
return typeof element.importData === 'function';
});
Promise.map(
models,
function(model) {
return migrateModel(model, model.definition.name, null) // don't want to break the promise chain
.then(findImportInfo)
.then(fetchRemoteData)
.then(processFetchedData)
.then(updateImportInfo)
.then(countLocalData)
.then(importResult)
.then(function(){
...
return Promise.resolve(); // don't want to break the promise chain
});
},
{concurrency: 1}
)
.then(function () {
debug('finished working on all the models one-by-one');
cb(null);
})
.catch(function (err) {
cb(err);
});

Async Waterfall function only call the first callback

I'm trying to play a bit with node and async waterfall function. This is my code:
var async = require('async');
var waterfall = function (req, res) {
async.waterfall([
_function1(req),
_function2,
_function3
], function (error, success) {
if (error) { alert('Something is wrong!'); }
console.log("success");
return alert('Done!');
});
};
function _function1 (req) {
return function (callback) {
var something = req.body;
console.log("first");
callback (null, something);
}
}
function _function2 (something, callback) {
return function (callback) {
console.log("second");
var somethingelse = function () { };
callback (err, somethingelse);
}
}
function _function3 (something, callback) {
return function (callback) {
console.log("third");
var somethingmore = function () { };
callback (err, somethingmore);
}
}
waterfall(function(){}, function(){});
But in the output I get only 'first'. Why another callbacks are not called?
You shouldn't return a function from _function2 and _function3. The reason it's being done for _function1 is to pass req in (which can be done in better ways, see below):
function _function2 (something, callback) {
console.log("second");
var somethingelse = function () { };
callback (err, somethingelse);
}
function _function3 (something, callback) {
console.log("third");
var somethingmore = function () { };
callback (err, somethingmore);
}
To get req into the waterfall, you could use this:
async.waterfall([
function(callback) { return callback(null, req); },
_function1,
_function2,
_function3
], ...);
Or (which I would prefer):
async.waterfall([
_function1.bind(this, req),
_function2,
_function3
], ...);
In both cases, you wouldn't need to return a function from _function1 either:
function _function1 (req, callback) {
var something = req.body;
console.log("first");
callback (null, something);
}

Resources