How to bind a helper stub to swagger-node with supertest? - javascript

I am using Swagger Node with express and I initialized the skeleton project. Swagger project create hello-world
Then inside the hello-world/api/controllers/hello_world.js I added a small modification to require a helper hello_helper.js and call its function helloHelper.getName().
'use strict';
let helloHelper = require('../helpers/hello_helper');
var util = require('util');
module.exports = {
hello: hello
};
function hello(req, res) {
var name = req.swagger.params.name.value || helloHelper.getName();
var hello = util.format('Hello, %s!', name);
res.json(hello);
}
hello-world/api/helpers/hello_helper.js
'use strict';
module.exports = {getName: getName};
function getName() {
return 'Ted';
}
I would like to stub helloHelper.getName() to return 'Bob' instead.
I can do so easily with:
hello-world/test/api/controllers/hello_world.js
// Create stub import of hello_helper
mockHelloHelper = proxyquire('../../../api/controllers/hello_world', { '../helpers/hello_helper': { getName: function () { return 'Bob'; } }
});
Using supertest how can I make swagger recognize my stub?
EDIT: Thanks to help from the answer below this solution worked for me.
var app, getNameStub, mockHelloHelper, request;
beforeEach(function (done) {
// Create stub import of hello_helper
mockHelloHelper = proxyquire('../../../api/controllers/hello_world', {
'../helpers/hello_helper': {
getName: function () {
return 'Bob';
}
}
});
app = require('../../../app');
request = supertest(app);
done();
});
...
it('should return a default string', function(done) {
request
.get('/hello')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.eql('Hello, Bob!');
done();
});
});

You need to initialize/require express app after you have proxyquired your dependency. Only then it can use your stubbed version of getName:
beforeEach(function () {
mockHelloHelper = proxyquire('../../../api/controllers/hello_world', {
'../helpers/hello_helper': {
getName: function () {
return 'Bob';
}
}
});
// initialize/require your app here
request = supertest(app);
});

Related

How can I stub a class in this particular case

I want to do some integration test skiping the last part of my endpoints when a class that I code (using sdk library), get data from a third party API. So my test case is the following:
describe('GET /getCustomer/:id', ()=>{
describe('get customer with id 1: ',()=>{
it('should respond success message', (done) => {
chai.request(app)
.get('/api/getCustomer/customerIDsample')
.end( function(err,res){
expect(res).to.have.status(SUCCESS);
done();
});
});
});
});
my Express NodeJS API works as:
route -> controller (req,res) -> service (my logic) -> gateway/client.
So the module that I need to stub is gateway/client. Let me show you the endpoint path from start to Client class:
route.js:
router.get('/getCustomer/:id', CustomerController.getCustomer
);
controller.js:
'use strict';
const { UNPROCESSABLE_ENTITY, SUCCESS, INTERNAL_SERVER_ERROR } = require('../../constants/httpCodes');
const CustomerService = require('../../services/customerService');
class CustomerController {
static async getCustomer (req, res) {
const customerID = req.params.id;
const customerService = new CustomerService(customerID);
try {
const getCustomer = await customerService.getCustomer()
return res.status(SUCCESS).send(getCustomer);
} catch (error) {
return res.status(INTERNAL_SERVER_ERROR).send({
"details": error
});
}
}
}
service.js:
'use strict';
const validate = require('jsonschema').validate;
const Client = require('../gateways/Client')
const ClientCustomerSchema = require('../schemas/ClientCustomerSchema');
class CustomerService {
constructor(customer) {
this.customer = customer;
}
async getCustomer() {
const client = new Client(this.customer);
try {
const newCustomer = await client.getCustomer();
return newCustomer;
} catch (error) {
throw error
}
}
}
client.js: this is my class to wrap an SDK from a API similar than paypal, Client is a fantasy name:
'use strict';
const Client = require('Client');
const { client } = require('../config/index');
class openPayClient {
constructor(customer) {
this.customer = customer;
this.client = new Client(
client.ID,
client.PRIVATE_KEY
);
}
async getCustomer() {
return await new Promise((resolve, reject) => {
this.client.customers.get(this.customer, function(error, body) {
if(error) {
reject(error)
} else {
resolve(body)
}
});
});
}
Of course I did researching but I found anything regarding stub classes in this kind of scenarios when actually you are not using the function/class explicitly in the test file. The module that I need to stub is Client.js, because this one use client.customer.get method that calls an external API through sdk library.

How to Import function in node.js?

I want have 2 functions in report.js file I want to one is report_data which is api controller and second is test I want to use test function in report_data function.
Below is my code of both functions.
var sequelize = require('../config/sequelize');
const Op = sequelize.Sequelize.Op;
var errors = require('../config/errors');
var error = errors.errors;
const helpers = require('../helpers/validations');
const logger = require('../helpers/logger').logger;
const fs = require('fs');
module.exports = {
report_data: async (req, res) => {
if (!req.body.id) {
logger.warn(error.MANDATORY_FIELDS);
return res.status(500).send(error.MANDATORY_FIELDS)
}
sequelize.sequelize.transaction(async (t1) => {
console.log('socket connected')
test(io)
let result = error.OK
logger.info(result);
return res.status(200).send(result)
}).catch(function (err)
logger.warn(err);
console.log(err)
return res.status(500).send(error.SERVER_ERROR)
})
},
test: function (io) {
console.log(io.sockets)
}
};
The easiest would be to declare test as a named global function:
function test(io) {
console.log(io.sockets)
}
module.exports = {
report_data: async (req, res) => {
// now you call call `test()` here
},
test: test,
}

How to mock a function in another function nodejs

Trying to write a unittest for the below module in /utility/sqsThing.js. However I'm having diffuculty mocking the sqs.sendMessage method. Anyone know how I should go about this. I'm using the sinon library, and mocha for running the tests.
The function that I'm trying to unittest utility/sqsThing.js:
const AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-1' });
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
const outputQueURL = 'https:awsUrl';
const SQSOutputSender = (results) => {
const params = {
MessageBody: JSON.stringify(results),
QueueUrl: outputQueURL,
};
// Method that I want to mock
sqs.sendMessage(params, function (err, data) {
if (err) {
console.log('Error');
} else {
console.log('Success', data.MessageId);
}
});
};
My attempt at mocking the sqs.sendMessage method in a unittest sqsThingTest.js:
const sqsOutputResultSender = require('../utility/sqsThing');
const AWS = require('aws-sdk');
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
const mochaccino = require('mochaccino');
const { expect } = mochaccino;
const sinon = require('sinon');
describe('SQS thing test', function() {
beforeEach(function () {
sinon.stub(sqs, 'sendMessage').callsFake( function() { return 'test' });
});
afterEach(function () {
sqs.sendMessage.restore();
});
it('sqsOutputResultSender.SQSOutputSender', function() {
// Where the mock substitution should occur
const a = sqsOutputResultSender.SQSOutputSender('a');
expect(a).toEqual('test');
})
});
Running this unittest with mocha tests/unit/sqsThingTest.js however I get:
AssertionError: expected undefined to deeply equal 'test'.
info: Error AccessDenied: Access to the resource https://sqs.us-east-1.amazonaws.com/ is denied..
It looks like the mock did not replace the aws api call. Anyone know how I can mock sqs.SendMessage in my test?
You could use rewire js it is a library that lets you inject mocked properties into your module you want to test.
Your require statement would look something like this:
var rewire = require("rewire");
var sqsOutputResultSender = rewire('../utility/sqsThing');
Rewire will allow you to mock everything in the top-level scope of you sqsThing.js file.
Also you need to return the value of sqs.sendMessage this will remove the issue expected undefined to deeply equal 'test'
Your original file would look the same just with a return statement.
//utility/sqsThing.js
const AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-1' });
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
const outputQueURL = 'https:awsUrl';
const SQSOutputSender = (results) => {
const params = {
MessageBody: JSON.stringify(results),
QueueUrl: outputQueURL,
};
// Method that I want to mock
return sqs.sendMessage(params, function (err, data) {
if (err) {
console.log('Error');
} else {
console.log('Success', data.MessageId);
}
});
};
You would then write your unit test as follows:
//sqsThingTest.js
var rewire = require("rewire");
var sqsOutputResultSender = rewire('../utility/sqsThing');
const mochaccino = require('mochaccino');
const { expect } = mochaccino;
const sinon = require('sinon');
describe('SQS thing test', function() {
beforeEach(function () {
sqsOutputResultSender.__set__("sqs", {
sendMessage: function() { return 'test' }
});
});
it('sqsOutputResultSender.SQSOutputSender', function() {
// Where the mock substitution should occur
const a = sqsOutputResultSender.SQSOutputSender('a');
expect(a).toEqual('test');
})
});
This example returns an object with a property of sendMessage but this could be replaces with a spy.
Rewire Docs
Try moving the declaration of sqsOutputResultSender after you have stubbed the sendmessage function
var sqsOutputResultSender;
const AWS = require('aws-sdk');
const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
const mochaccino = require('mochaccino');
const { expect } = mochaccino;
const sinon = require('sinon');
describe('SQS thing test', function() {
beforeEach(function () {
sinon.stub(sqs, 'sendMessage').callsFake( function() { return 'test' });
sqsOutputResultSender = require('../utility/sqsThing');
});
afterEach(function () {
sqs.sendMessage.restore();
});
it('sqsOutputResultSender.SQSOutputSender', function() {
// Where the mock substitution should occur
const a = sqsOutputResultSender.SQSOutputSender('a');
expect(a).toEqual('test');
})
});

refactor NodeJs functions

I have a big app.js file and want to split the code. I took all my routes into a module called routes.js
module.exports = function(app){
app.get('/', function (req, res) {
res.redirect('/page1');
});
app.get('/page1', function (req, res) {
res.render('page1');
});
app.get('/page2/:id', function (req, res) {
res.render('page2', {
val: Number(req.params.id)
});
});
}
and in my app.js I call
const routes = require('./Server/routes')(app);
So this works fine.
I have some functions like
function loadData(id, callback) {
fs.readFile('./database.json', 'utf8', function (err, data) {
var json = JSON.parse(data);
var arr = json.arr;
var obj = arr.find(e => e.id === Number(id));
callback(obj);
});
}
and want to have them in separate files too. How can I do this? I am able to export one function but how can I export more than one?
Like
module.exports = function(){
function sayHello(){
console.log("Hello");
}
function calc(){
return 5 + 7;
}
}
require the module and call
myModule.sayHello();
var num = myModule.calc();
In your new module you can export an object and define your functions inside object
module.export = {
sayHello: function() {
console.log("Hello");
},
calc: function() {
return 5 + 7;
}
}
// usage: const mymodule = require('path/to/your/file');
also you can export a function and define your needed functions in prototype
function mymodule(someArgsIfNeeded) {
// do some initialization
}
mymodule.prototype.sayHello = function() {
console.log("Hello");
}
mymodule.prototype.calc = function() {
return 5 + 7;
}
module.export = mymodule
// usage: const mymodule = require('path/to/your/file')(someArgsIfNeeded);

node js unit testing: mocking require dependency

I am having issues writing unit test for the following setup as a jira.js file (in a node.js module):
var rest = require('restler'); // https://www.npmjs.com/package/restler
module.exports = function (conf) {
var exported = {};
exported.getIssue = function (issueId, done) {
...
rest.get(uri).on('complete', function(data, response) {
...
};
return exported;
};
Now, i want to write unit test for my getIssue function. 'restler' is a REST client through which i make REST calls to the JIRA API to get a JIRA issue via my code.
So to be able to test createIssue(..), I want to be able to mock the 'rest' var in my Jasmine unit tests.
How can i mock this method? Please give me some pointers so that i can go ahead. I have tried using rewire but i have failed.
This is what i have so far which does not work (ie. getIssue method turns out to be undefined):
var rewire = require("rewire");
var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();
var cfg = require("../../../config.js").Configuration;
var jiraModule = rewire("../lib/jira")(cfg);
var sinon = require("sinon");
var should = require("should");
// https://github.com/danwrong/restler
var restMock = {
init : function () {
console.log('mock initiated'+JSON.stringify(this));
},
postJson : function (url, data, options) {
console.log('[restler] POST url='+url+', data= '+JSON.stringify(data)+
'options='+JSON.stringify(options));
emitter.once('name_of_event',function(data){
console.log('EVent received!'+data);
});
emitter.emit('name_of_event', "test");
emitter.emit('name_of_event');
emitter.emit('name_of_event');
},
get : function (url, options) {
console.log('[restler] GET url='+url+'options='+JSON.stringify(options));
},
del : function (url, options) {
console.log('[restler] DELETE url='+url+'options='+JSON.stringify(options));
},
putJson : function (url, data, options) {
console.log('[restler] PUT url='+url+', data= '+JSON.stringify(data)+
'options='+JSON.stringify(options));
}
};
var cfgMock = {
"test" : "testing"
};
jiraModule.__set__("rest", restMock);
jiraModule.__set__("cfg", cfgMock);
console.log('mod='+JSON.stringify(jiraModule.__get__("rest")));
describe("A suite", function() {
it("contains spec with an expectation", function() {
restMock.init();
restMock.postJson(null, null, null);
console.log(cfg.jira);
// the following method turns out to be undefined but when i console.log out the jiraModule, i see the entire code outputted from that file
jiraModule.getIssue("SRMAPP-130", function (err, result) {
console.log('data= '+JSON.stringify(result));
});
expect(true).toBe(true);
});
});
If someone can guide me on how to mock the 'rest' require dependency & unit test this method that will be very helpful.
Also, how should i mock the 'conf' being passed to module.exports?
thanks
You could use proxyquire or mockery to stub/mock the dependencies.
In the below example I have used proxyquire. Hope it helps.
/* ./src/index.js */
var rest = require('restler');
module.exports = function (conf) {
var exported = {};
exported.getIssue = function (issueId, done) {
var uri = '';
var reqObj = '';
var service = {
auth : ''
};
rest.postJson(uri, reqObj, service.auth).on('complete', function(data, response) {
done(data, response);
});
};
return exported;
};
/* ./test/index.js */
var proxyquire = require('proxyquire');
var assert = require('chai').assert;
var restlerStub = {
postJson: function() {
return {
on: function(event, callback) {
callback('data', 'response');
}
}
}
}
var index = proxyquire('../src/index', {'restler': restlerStub})();
describe('index', function() {
it('should return the desired issue', function(done) {
var issue = index.getIssue('issueId', function(data, response) {
assert.equal(data, 'data');
assert.equal(response, 'response');
done();
})
});
});
/* ./package.json */
{
"scripts": {
"test": "mocha"
},
"dependencies": {
"restler": "^3.4.0"
},
"devDependencies": {
"chai": "^3.4.1",
"mocha": "^2.3.4",
"proxyquire": "^1.7.3"
}
}

Categories