I'm looking to change requestHandler.value to 5 for my functional styled tests.
When running the suite, creating 1000 documents in the db is not really an option, so is it possible to change it's value programmatically before running the suite and then reset it afterwards? I can create 5 documents in db before the test to work with.
Of coarse I can stub countDocumentsInDb() in unit tests to return what I need, but I've simplified logic below for the sake of the question.
app.js:
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var requestHandler = require('./lib/requestHandler.js');
var PORT = 4000;
app.route('/validate')
.get(function(req, res) {
requestHandler.process(req, res);
});
if (!module.parent) {
server.listen(PORT, function(err) {
if (err) {
return;
}
});
}
module.exports = app;
requestHandler.js:
var requestHandler = {
value: 1000,
process: function(req, res) {
numberOfDocumentsInDb = countDocumentsInDb();
if (numberOfDocumentsInDb === this.value) {
res.send(true);
} else {
res.send(false);
}
}
};
module.exports = requestHandler;
FVT style test ..
var Promise = require('promise');
var request = require('supertest');
var chai = require('chai');
chai.should();
var server = require('../../app.js');
describe('app.js', function() {
describe('/validate', function() {
it('should return true if number of documents in db matches pre-defined value', function(done) {
var fvtPromise = new Promise(function(fulfill) {
request(server)
.get('/validate')
.expect(200)
.end(function(err, res) {
if (err) {
throw err;
}
res.body.should.equal(true);
fulfill(null);
});
});
fvtPromise.done(function() {
done();
});
});
});
});
You can play with the require.cache, that will allow you to modify the values of requestHandler.
Is just an example I hope you get the idea.
- In the before each modify the require cache and set your test values
-In the after each set back the original values
-Please notice that the const server = require('./app.js'); is inside the test, so it will take the cache vales
e.g.
describe('test with cache', function(){
require('./requestHandler');
let originalValues;
beforeEach(function() {
originalValues = require.cache[ require.resolve('./requestHandler') ].exports;
require.cache[ require.resolve('./requestHandler') ].exports = {
value:5,
process: function(req, res) {
//other stuff
}
};
});
afterEach(function() {
require.cache[ require.resolve('./requestHandler') ].exports = originalValues;
});
it('should pass', function(){
const server = require('./app.js');
var fvtPromise = new Promise(function(fulfill) {
request(server)
.get('/validate')
.expect(200)
.end(function(err, res) {
if (err) {
throw err;
}
res.body.should.equal(true);
fulfill(null);
});
});
fvtPromise.done(function() {
done();
});
expect(true).to.be.true;
});
});
Related
I am new to Node js and express. I trying to query my Azure database to get the list of patients(MR number). I am getting the list but I think the request.on() runs as an asynchronous function so first, it will render the HTML page without any list and after executing the function Node Js exit executing.
Code:
var express = require('express');
var router = express.Router();
//For database
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
function mrquery(connection) {
request = new Request(
"SELECT DISTINCT MRNO FROM Transaction_Record",
function(err, rowCount, rows) {
console.log(rowCount + ' row(s) returned');
process.exit();
}
);
request.on('row', function(columns) {
columns.forEach(function(column) {
console.log(column.value);
});
});
connection.execSql(request);
}
/* GET home page. */
router.get('/', async function(req, res, next) {
var connection = req.app.get('connection');
var isconnected = req.app.get('isconnected');
if (isconnected) {
mrquery(connection)
res.render('index', {
title: 'Express'
});
} else {
console.log('Not Connected');
res.render('error', {
error: 'error'
});
}
});
module.exports = router;
Thanks in advance.
I'm learning unit testing. So far I was able to run simple tests like "Add two numbers and test if they are above 0", but I want to build a REST API using TDD. So far I have this:
My routes/index.js file:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function (req, res, next) {
res.send({val: true});
});
module.exports = router;
My index.test.js file:
var mocha = require('mocha');
var assert = require('chai').assert;
var index = require('../routes/index');
describe('Index methods', () => {
it('Returns true', done => {
index
.get('http://localhost:3000')
.end(function (res) {
expect(res.status).to.equal(200);
done();
})
})
});
I user a tutorial to do this, but when I try to run this I get:
TypeError: index.get(...).end is not a function
So I'm guessing there is something wrong, but have no idea what. That's my first day learning TDD so if you see anything stupid please let me know.
Doing this:
it('Returns true', done => {
var resp = index.get('http://localhost:3000/');
assert.equal(resp.val === true);
done();
})
Also results in an error:
AssertionError: expected false to equal undefined
1. Install the dev dependencies for mocha
chai: assertion library for node and browser,
chai-http: HTTP Response assertions for the Chai Assertion Library.
2. You need to export your server,
'use strict';
/*eslint no-console: ["error", { allow: ["warn", "error", "log"] }] */
const express = require('express');
const app = express();
//...
const config = require('config');
const port = process.env.PORT || config.PORT || 3000;
//....
app.listen(port);
console.log('Listening on port ' + port);
module.exports = app;
3. Write your tests as:
If your test script is users.spec.js,it should start by:
// During the rest the en variable is set to test
/* global describe it beforeEach */
process.env.NODE_ENV = 'test';
const User = require('../app/models/user');
// Require the dev-dependencies
const chai = require('chai');
const chaiHttp = require('chai-http');
// You need to import your server
const server = require('../server');
const should = chai.should();
// Set up the chai Http assertion library
chai.use(chaiHttp);
// Your tests
describe('Users', () => {
beforeEach((done) => {
User.remove({}, (err) => {
done();
});
});
/**
* Test the GET /api/users
*/
describe('GET /api/users', () => {
it('it should GET all the users', (done) => {
chai.request(server)
.get('/api/users')
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('array');
res.body.length.should.be.eql(0);
done();
});
});
});
// More test...
});
You can take a look at my repository, Github - Book Store REST API
const chai = require('chai');
const expect = require('chai').expect;
const chaiHttp = require('chai-http');
chai.use(chaiHttp);
first install chai
it('Returns true', done => {
return chai.request(index)
.get('/')
.then(function (res) {
expect(res.status).to.equal(200);
done();
})
})
var mocha = require('mocha');
var assert = require('chai').assert;
var index = require('./index');
var req = require('supertest');
describe('Index methods', () => {
it('Returns true', done => {
req(index)
.get('/')
.end(function (res) {
expect(res.status).to.equal(200);
done();
})
})
});
also in your terminal type npm i supertest --save-dev
simple test case to check if the server is running properly.
const chai = require('chai'),
chaiHttp = require('chai-http'),
server = require('../app'),
faker = require('faker'),
should = chai.should();
chai.use(chaiHttp);
describe('Init', function () {
it('check app status', function (done) {
chai.request(server).get('/').end((err, res) => {
should.not.exist(err);
res.should.have.status(200);
done();
})
});
});
Test Cases for get API
describe('/Get API test', function () {
it('Check the api without user id parameter', function (done) {
chai.request(server).get('/post-list').end((err, res) => {
should.not.exist(err);
res.should.have.status(401);
res.body.should.be.a('object');
res.body.should.have.property('message');
res.body.should.have.property('message').eql('User Id parameter is missing');
done();
})
});
it('Check the api with user id. Success', function (done) {
chai.request(server).get('/post-list?user_id=1').end((err, res) => {
should.not.exist(err);
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('userId');
res.body.should.have.property('title');
res.body.should.have.property('body');
done();
})
});
});
Test Case for Post API
describe('/POST API test', function () {
it('Check the api without parameters . failure case', function (done) {
chai.request(server).post('/submit-data').send({}).end((err, res) => {
should.not.exist(err);
res.should.have.status(401);
res.body.should.be.a('object');
res.body.should.have.property('message');
res.body.should.have.property('message').eql('Mandatory params are missing!');
done();
})
});
it('Check the API with valid parameters. Success', function (done) {
chai.request(server).post('/submit-data').send({name:faker.name.firstName(),email:faker.internet.email()}).end((err, res) => {
should.not.exist(err);
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('message');
res.body.should.have.property('message').eql('data saved successfully');
done();
})
});
});
Add test cases as per the different case available in your API.
Find here the basic terminologies and complete sample application to proceed: https://medium.com/#pankaj.itdeveloper/basics-about-writing-tests-in-nodejs-api-application-4e17a1677834
newbie question is following:
I'm having a hard time to get the EventEmitter to work. I already considered the documentation and several best-practive tutorials like this one: https://code.tutsplus.com/tutorials/managing-the-asynchronous-nature-of-nodejs--net-36183
The problem is, that within the user.js (Class) this.emit() hits nothing. userRoutes.js doesn't trigger any user.on(), and I really don't know why..
Any suggestions are appreciated. Hints for better structuring also. My goals are centralized endpoints (well-readable) and reusing the code for every module (like user or products/orders) within different modules, e.g. calling to update an order out of the user-endpoint.
So, let's assume, you have your node.js-Server with a module configuration, router and several classes, like this:
/server.js
global.__base = __dirname + "/";
var server = require("http").createServer();
var routes = require("./v2");
var initialize = require(global.__base + "config");
var app = initialize.globalModules();
app.use('/api/v2', routes);
app.listen('8090');
/config.js
var db;
module.exports = {
globalModules: function() {
// load the global modules
var app = require("express")();
var bodyParser = require("body-parser");
//setUp app
app.use(bodyParser.json());
return app;
},
db: function() {
var mysql = require('mysql');
var db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'node_docx'
});
db.connect(function(err) {
if (err) throw err;
});
return db;
}
};
/v2/index.js (routes)
var userRoutes = require('./userRoutes');
var routes = require('express').Router();
routes.use("/user", userRoutes);
//routes.use("/product", productRoutes);
//routes.use("/order", orderRoutes);
//...
routes.use('*', function(req, res) {
res.status(404).send({code: 404, message: 'ERR', data: "Unknown target."});
});
module.exports = routes;
/v2/userRoutes.js
var User = require("./routes/user.js");
var user = new User();
var route = require('express').Router();
route.get("/", function(req, res) {
user.on('error', function(err) {
res.status(400).send({code: 900, message: 'ERR', data: err});
});
user.on('failure', function() {
res.status(404).send({code: 901, message: 'ERR', data: "User not found!"});
});
user.on('success', function(result) {
res.status(200).send({code: 200, message: 'OK', data: result});
});
user.getAll();
});
module.exports = route;
/v2/routes/user.js
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var initialize = require(global.__base + "/config");
var db = initialize.db();
function User() {
EventEmitter.call(this); //edit: added, but has not solved the problem
var self = this; //solved it!
function _checkForErrors(error, rows, reason) {
if (error) {
self.emit('error', error);
return true;
}
if (rows.length < 1) {
self.emit('failure', reason);
return true;
}
return false;
}
function _getData(error, rows) {
if (_checkForErrors(error, rows)) {
return false;
} else {
self.emit('success', rows);
}
}
function getAll() {
db.query("SELECT * FROM patient", _getData);
}
this.getAll = getAll;
}
util.inherits(User, EventEmitter);
module.exports = User;
It's quite simple, you forgot EventEmiter.call(this) in function User.
function User() {
EventEmitter.call(this);
var self = this;
function _checkForErrors(error, rows, reason) {
if (error) {
self.emit('error', error);
return true;
}
if (rows.length < 1) {
self.emit('failure', reason);
return true;
}
return false;
}
function _getData(error, rows) {
if (_checkForErrors(error, rows)) {
return false;
} else {
self.emit('success', rows);
}
}
function getAll() {
db.query("SELECT * FROM patient", _getData);
}
this.getAll = getAll;
}
Why is users undefined?
db.js:
var MongoClient = require('mongodb').MongoClient
var users;
MongoClient.connect('mongodb://127.0.0.1:27017/ExpressApp2', function(err, db) {
users = db.collection('usercollection');
users.find().each(function(err, doc) {
console.log(doc);
});
});
index.js
var express = require('express');
var router = express.Router();
/* GET Userlist page. */
router.get('/userlist', function(req, res) {
var users = require('../db').getUsers();
if (users==undefined)
res.send('undefined');
else
res.send('found something');
});
module.exports = router;
The collection is correctly retrieved from Mongo and logged to screen, but users in index.js gives undefined.
MongoClient.connect('mongodb://127.0.0.1:27017/ExpressApp2', function(err, db) {
users = db.collection('usercollection');
users.find().each(function(err, doc) {
console.log(doc);
});
});
should be
module.exports.getUsers = function() {
MongoClient.connect('mongodb://127.0.0.1:27017/ExpressApp2', function(err, db) {
return db.collection('usercollection');
});
}
I'm presuming that
users.find().each(function(err, doc) {
console.log(doc);
});
is part of your debugging and what you actually want to return is the user collection. The important bit is adding the block to module.exports as getUsers().
I got it to work with this async call in the end.
index.js
router.get('/userlist', function(req, res) {
var d = require('../db');
d.getUsers('input', function(users) {
users.each(function(err, doc) {
res.send(doc);
return false;
});
});
});
In db.js you are not using module.exports to export your users.
Your code in index.js suggests db.js exports an object with a getUsers function but it does not.
I've got a simple express app that looks like this:
var SendMandrillTemplate = require('send-mandrill-template');
var sendMandrillTemplate = new SendMandrillTemplate('api-key-goes-here');
var app = require('express')();
app.get('/', function(req, res, next) {
sendMandrillTemplate.sendTemplate(
'template-name-goes-here',
'email#here.com', {
value: 123
},
function(err) {
if (err) {
res.send('ERR - ', err)
} else
res.send('DONE')
});
});
module.exports = app;
I export the app object, so I can mount this in a separate server.js like this -
var app = require('./app')
app.listen(1234, function() {
console.log('Running on port 1234');
});
This is to enable me to use supertest a bit easier.
Here's my test so far:
var app = require('./app')
var request = require('supertest')
var SendMandrillTemplate = require('send-mandrill-template');
describe('GET /', function() {
var sendTemplateStub;
before(function() {
//I think i need to setup a spy on the created instance of SendMandrillTemplate.sendTemplate
//sendTemplateStub = //?
});
it('calls sendTemplate on sendMandrillTemplate instance', function(done) {
request(app)
.get('/')
.expect(200)
.end(function(err, res) {
if (err) throw err;
//assert sendTemplateStub was called with 'template-name-goes-here'
//etc...
done();
})
})
})
As you can see, I'm having trouble stubbing the SendMandrillTemplate constructor
If I wasn't newing up an instance of SendMandrillTemplate I could do something like:
sendTemplateStub = sinon.stub(SendMandrillTemplate, 'sendTemplate')
But of course, in this scenario this won't work...
You can get away with something as simple as
var SendMandrillTemplate = require('send-mandrill-template');
sinon.stub(SendMandrillTemplate.prototype, 'sendTemplate');