Testing for server in Koa - node.js

I am using Koa for web development in NodeJS, I have a server file, which does nothing but to start the server and initialise few middlewares. Following is the sample code
server.js
const Koa = require('koa');
var Router = require('koa-router');
var bodyParser = require('koa-bodyparser');
var app = new Koa();
var router = new Router();
app.use(bodyParser());
router.post('/abc', AbcController.abcAction);
router.post('/pqr', PqrController.pqrAction);
app.use(router.routes());
app.listen(3000);
When we run npm start the server will start on 3000 port and now I want to write unit test case for this file using mocha, chai and sinon.
One way is to create a test file lets say server_test.js and do something like the following(just an example):
var server = require(./server);
server.close();
For this we need to add the following lines to server.js
var server = app.listen(3000);
module.exports = server;
Is this a good practice to do? I think we should not expose server in this fashion?
As we don't have self created function here in this file, is testing really required?
Should we also exclude such files from sonarqube coverage?
Any other better suggestion is always welcome. Need your help guys. Thank you.

You can use chai-http for testing the endpoint
this is what I use for my project
const chai = require('chai');
const chaiHttp = require('chai-http');
const expect = chai.expect;
const app = require('../app');
describe('/GET roles', function () {
it('should return bla bla bla',
function (done) {
chai.request(app)
.get('/roles')
.end(function (err, res) {
expect(res.status).eql(200)
expect(res.body).to.have.property('message').eql('Get role list success');
expect(res.body).to.have.property('roles');
expect(err).to.be.null;
done();
});
}
);
});

There are primarily 2 ways through which you can actually handle rest cases.
One is to put your test cases along with your source code file. ( in your case it would be server.spec.js ). I personally prefer this way as it encourages code modularity and make your modules totally independent.
Another way is to create another directory, let say test, where you can put your entire test cases according to same directory structure as followed by the main application. This is really useful for applications where test cases are only considered while they are in development phase and then at time of production you can simply ignore sending these files.
Also, I usually prefer following the concepts of functional programming as it really helps to test each block of code independently.
Hope this helps

Related

Unit Testing Azure Mobile App (Node.js) Locally

Please don't tell me I should have been testing before now. I don't disagree, and that's not the point of this question. If it helps, assume I'm doing TDD perfectly and I'm asking this question about a brand new project. ;-)
I've been developing an Azure Mobile App with a Node.js backend for some time now. I have done so completely dependent on Microsoft hosting the service (which I think makes sense). Now, though, I'd like to have some unit tests running against my code, but I'm at a loss for how to get from a functional, Microsoft-hosted Azure Mobile App to a locally-hosted version where I can run my tests.
A big assumption here is that the testing will run much faster if I'm running them locally. A lot of my code interacts with a SQL Server database, so please tell me if this is an incorrect assumption.
Anyway, I've gotten Node.js and NPM set up on my Mac. I've gone through some basic tutorials on creating a Node.js site from scratch, and I got the ubiquitous "Hello World" Node.js website working locally. I even apparently got a basic Azure Mobile site up and running (at least, I got the "This mobile app has been successfully created" homepage to show up).
I've also done some reading on Mocha and Chai for Unit Testing in Node.js. I even got through some of their first examples and had some simple tests working.
What's confusing me is how to move from the super-basic Mocha test examples to more real-world testing of my actual code.
For instance, here's a Mocha test example (taken from semaphore):
var expect = require("chai").expect;
var converter = require("../app/converter");
describe("Color Code Converter", function() {
describe("RGB to Hex conversion", function() {
it("converts the basic colors", function() {
var redHex = converter.rgbToHex(255, 0, 0);
var greenHex = converter.rgbToHex(0, 255, 0);
var blueHex = converter.rgbToHex(0, 0, 255);
expect(redHex).to.equal("ff0000");
expect(greenHex).to.equal("00ff00");
expect(blueHex).to.equal("0000ff");
});
});
describe("Hex to RGB conversion", function() {
it("converts the basic colors", function() {
var red = converter.hexToRgb("ff0000");
var green = converter.hexToRgb("00ff00");
var blue = converter.hexToRgb("0000ff");
expect(red).to.deep.equal([255, 0, 0]);
expect(green).to.deep.equal([0, 255, 0]);
expect(blue).to.deep.equal([0, 0, 255]);
});
});
});
It's no real surprise that this code will fail until ../app/converter.js is created with the appropriate functions exported. Ok, so I try to adapt that kind of thinking to, say, my Login method, and I'm unable to connect the dots.
My Login code happens to reside at ../api/Authentication/Login.js in the file structure. Is that going to matter to my test code, or can I simply reference something like .post('Login')? Either way, here's an overview of my Login.js file:
var auth = require('azure-mobile-apps/src/auth'),
bcrypt = require('bcrypt-nodejs');
module.exports = {
post: function (req, res, next) {
// Actual code removed
}
};
I have no idea how to construct the req, res, and next variables/parameters. When it comes to this point, an article I read by Michael Herman (link) seems to be closer to what I'm trying to do.
In that article, a test-server.js file is set up with contents like this:
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('../server/app');
var should = chai.should();
chai.use(chaiHttp);
describe('Blobs', function() {
it('should list ALL blobs on /blobs GET', function(done) {
chai.request(server)
.get('/blobs')
.end(function(err, res){
res.should.have.status(200);
done();
});
});
});
This seems to be referencing /blobs because in ../server/models/blob.js, there is this line:
module.exports = mongoose.model('blobs', blobSchema);
That's what makes me think that maybe the following lines (in my Login.js) are doing something more structured behind the scenes:
module.exports = {
post:
Anyway, this is just the tip of the iceberg. My Azure Mobile App has environment variables and connection strings, etc. Is it possible for me to get all of that running on my local machine, or am I better off to implement my testing in Azure's portal somehow?
If I should do it locally, how can I get that set up?
If I should do it in Azure's portal, how do I begin there?

Small api on node.js

maybe someone have example for creating small API on node.js
Example, i have function this function will return string
I need call this string from postman or inside any another project with http.
What better for create this API?
Maybe someone know good guide? I worked before with node.js only like web-server
It is best practice that building API's in nodejs with express.Here is a code in which function returns a string. You need to export it. And require the file that contains exported value in your project file with the file path. Here is my function code where I am returning a string value. func.js
var string;
function myfunc(param,callback){
var str="hello";
callback(null,str);
}
myfunc('aaa',function(err,result){
if(err){
console.log(err);
}
else{
exports.string=result;
}
});
Here is my routes file and here I am calling the string from func.js and I named this file as str.js
var http = require('http');
var express = require('express');
var main = require('./func.js');//path of file
var org = main.string;
var app = express();
app.get('/str',function(req,res){
console.log(org);
res.send(org);
});
app.listen(3000,function(){
console.log("Server listening on 3000");
});
Run the code as node str.js and in postman run the url as http://localhost:3000/str and you can see the returned string in both response and in terminal.
Hope this helps...
This tutorial shows you how to build an API in Node.js with Express.
EDIT: You can skip the database part if you don't need it.

How would I test sending a route with mocha/chai/superagent in express?

it('sends login page if we\'re logged out at /', function (done) {
superagent.get('http://localhost:4000/').end(function(err, res){
if(err) {return done(err)}
expect(res).to.have.property('status', 200);
//how would i do something like this?
expect(res.viewRendered).to.be.equal('index.ejs')
done();
});
});
I'm new to testing and I hate it.. a lot. I'm trying to learn the basics and it's the most frustrating learning curve I've ever experienced. I've been looking up documentation for hours and still haven't been able to figure out how to check which route has been rendered
I would go about this another way: instead of relying on the output of the request, and match that up against a template (which can be quite difficult unless you add some sort of identifier to each template, which doesn't feel entirely right), you can take advantage of some internals of Express, and specifically on how it renders templates.
The Express documentation states the following (here):
Express-compliant template engines such as Pug export a function named __express(filePath, options, callback), which is called by the res.render() function to render the template code.
You are not using Pug, but EJS, but the same principle applies: the ejs module exports a function called __express which will be called with full path of the template that should be rendered. And that also happens to be what you want to test for!
So the question now becomes: "how can you test that ejs.__express() gets called with the proper template name?". Answer: you can spy on it.
My favorite module for this is Sinon, so the example below will use that. Sinon is great to spy on existing functions, or to make them do entirely different things if you want.
As an example, I will use the following, very simple, Express app:
// app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.render('index.ejs', { foo : 'bar' });
});
module.exports = app;
We want to test if, when / is requested, the template index.ejs gets rendered.
Instead of using superagent, I'll be using supertest, which is meant for testing HTTP apps.
Here's the annotated Mocha test file:
// Import the Express app (from the file above), which we'll be testing.
const app = require('./app');
// Import some other requirements.
const expect = require('chai').expect;
const supertest = require('supertest');
const sinon = require('sinon');
// Import the EJS library, because we need it to spy on.
const ejs = require('ejs');
// Here's the actual test:
it('sends login page if we\'re logged out at /', function (done) {
// We want to spy on calls made to `ejs.__express`. We use Sinon to
// wrap that function with some magic, so we can check later on if
// it got called, and if so, if it got called with the correct
// template name.
var spy = sinon.spy(ejs, '__express');
// Use supertest to retrieve / and make sure that it returns a 200 status
// (so we don't have to check for that ourselves)
supertest(app)
.get('/')
.expect(200)
.end((err, res) => {
// Pass any errors to Mocha.
if (err) return done(err);
// Magic! See text below.
expect(spy.calledWithMatch(/\/index\.ejs$/)).to.be.true;
// Let Sinon restore the original `ejs.__express()` to its original state.
spy.restore();
// Tell Mocha that our test case is done.
done();
});
});
So what's this magic:
spy.calledWithMatch(/\/index\.ejs$/)
It means: "return true if the function that was being spied on (ejs.__express()) got called with a first argument that matches the regular expression \/index\.ejs$". Which is what you want to test for.
The reason I'm using a regular expression here is because I'm lazy. Because the first argument (filePath in the quote above) will contain the full path to the template file, it can be quite long. You can directly test for it if you want:
spy.calledWith(__dirname + '/views/index.ejs')
But that would break if the location of the template directory got changed. So, like I said, I'm lazy, and I'll use a regular expression match instead.
With tools like supertest, sinon and chai, testing can actually become fun (honest!). I have to agree that the learning curve is rather steep, but perhaps that an annotated example like this can help you get a better idea on what's possible and how to go about it.

How do I overload the functionality of app.listen in expressjs

I've been trying to create (basically) a factory function that configures and builds an expressjs server for a dozen smaller specialized servers I have. For part of this I want to augment the listen function.
I would like to know the best way to go about this. I'm also looking for a reusable design choice here.
Server is created normally:
var httpServer = express();
...
Because of the way express is designed (Not sure if I am correct) I cannot access a {whatever}.prototype.listen. So I have come up with two approaches.
Using an additional variable in the current scope:
var oldListen = httpServer.listen;
httpServer.listen = function(callback){
...
oldListen.call(httpServer, options.port, options.host, function(){
...
if ( typeof callback == 'function' ) callback();
});
};
Which works and is fairly straight forward but then I have a variable hoisting wart. I also have a closure solution, but I think it may be too obtuse to be practical:
httpServer.listen = (function(superListen){
return function(callback){
...
superListen.call(httpServer, options.port, options.host, function(){
...
if ( typeof callback == 'function' ) callback();
});
};
})(httpServer.listen);
Both examples are part of the factory context and I am intentionally reducing the arguments passed to the function.
Any help would be appreciated.
If you insist on "overloading", make sure you implement the original footprint (such is the nature of overloading). Express listen is just an alias to node's internal http listen method:
server.listen(port, [host], [backlog], [callback]);
UPDATE: Express even suggests using node's server API for custom implementations: http://expressjs.com/4x/api.html#app.listen
Otherwise, you should create your own custom listen method which would be defined like:
httpServer.myCustomListen = function (callback) {
httpServer.listen.call(httpServer, options.port, options.host, callback);
}
The second option is your best bet, but in order for it to work, you must extend the express library. Express is open source and hosted on Github. Fork it and modify it as you please. Periodically pull in new updates so you stay up-to-date with the core library. I do this all the time with node modules.
There are two benefits from doing it this way:
You have complete control to customize the code however you see fit while staying up to date with the code written by the original authors.
If you find a bug or build a cool feature, you can submit a pull request to benefit the community at large.
You would first fork the repository, then grab the URL for your fork, clone it, and then add a reference to the original "upstream" repo:
git clone [url_to your_fork]
cd express
git remote add upstream git#github.com:strongloop/express.git
Then you can push changes to your own repo (git push). If you want to get updates from the original repo, you can pull from the upstream repo: git pull upstream master.
If you want to add your custom fork of express as an npm module for a project, you would use the following:
npm install git://github.com/[your_user_name]/express.git --save
As Victor's answer pointed out, express's prototype is in express/lib/application.js. That file is used to build express and is exported via the application namespace in express/lib/express.js. Therefore, the .listen function can be referenced using express.appliction.listen.
One can use this method then: (similar to Victor's method)
var express = require('express');
express.application._listen = express.application.listen;
express.application.listen = function(callback) {
return this._listen(options.port, options.host, callback);
};
One can also use Lo-dash's _.wrap function if you don't want to store the base function in a variable yourself. It would look something like this:
var express = require('express');
var _ = require('lodash');
express.application.listen = _.wrap(express.application.listen, function(listenFn) {
return listenFn(options.port, options.host, callback); // Called with the same this
};
However, using these methods would run into the problems that you mentioned in your question (variable hoisting, creating an extra variable). To solve this, I would usually create my own subclass of express.application and replace the .listen function in that subclass and tell express to use that subclass instead. Due to express's current structure, however, you cannot replace express.application with your own subclass without overriding the express() function itself.
Hence, what I would do is to take over express.application.listen completely since it is only 2 lines. It is rather simple!
var express = require('express');
var http = require('http');
express.application.listen = function(callback) {
return http.createServer(this).listen(options.port, options.host, callback);
};
You can even make an https option!
var express = require('express');
var http = require('http');
var https = require('https');
express.application.listen = function(callback) {
return (options.https ? http.createServer(this) : https.createServer({ ... }, this))
.listen(options.port, options.host, callback);
};
Note: One of the other answers mentions forking express and modifying it. I would have a tough time justifying that for such a small function.
You should be able to easily overload the express listen function. You can access it in the following Object path: express.application.listen
So, you can implement something like this:
var express = require('express');
express.application.baseListen = express.application.listen;
express.application.listen = function(port) {
console.log('Port is: ' + port);
this.baseListen(port);
};
The implementation of the listen function is in the following path under the express module folder: node_modules\express\lib\application.js
Bind and listen for connections on the given host and port. This method is identical to node's http.Server#listen().
var express = require('express');
var app = express();
app.listen(3000);
The app returned by express() is in fact a JavaScript Function, designed to be passed to node's HTTP servers as a callback to handle requests. This allows you to provide both HTTP and HTTPS versions of your app with the same codebase easily, as the app does not inherit from these (it is simply a callback):
var express = require('express');
var https = require('https');
var http = require('http');
var app = express();
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
The app.listen() method is a convenience method for the following (if you wish to use HTTPS or provide both, use the technique above):
app.listen = function(){
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
Reference:http://expressjs.com/api.html
Hope This helps.

How to Make a Call to Koa.js App Instance for Unit Tests

I don't know how I'd term this maybe 'static call to a koa router'? Does that seem like the right wordage here for what I'm really trying to accomplish if you were to talk about it technically?
Anyway, I'm using koa-router and I'm coding unit tests (not integration tests). So I do not want to invoke .listen() on my koa app because of that reason...it would create an http server which now makes my test an integration tests.
Instead in my test I simply want to make a straight call to the app object instance and call a route and be able to return no results and check that I returned no results in the response.
How can you do that? I can't find an example and I've tried all sorts of pseudo code attemps agains the koa app object.
If you want to test the function that koa-router routes to then just perform a unit test on that function and leave the routing out of it.
To me it sounds like you've got a file such as app.js and it contains all your code. What you can do is create a router.js file to put you route bindings and a services.js file where you can put your application logic.
So for example app.js might look like:
var koa = require("koa");
var app = module.exports = koa();
var router = require('./router.js');
app.use(router.unsecured.middleware());
app.listen(3000);
And router.js might look like:
var router = require("koa-router");
var service = require("./services.js");
var unsecured = module.exports.unsecured = new router();
unsecured.post('/account/signin', service.signinUser);
unsecured.post('/account/register', service.registerUser);
And services.js might look like:
module.exports.signinUser = function*(signinDetails) {
// contains your application signin logic
};
module.exports.registerUser = function*(registerDetails) {
// contains your application register logic
};
So in this manner you can individually test services.js. I don't see any value in individually testing router.js since it is so trivial. As #Dan Pantry shows you can test routing as part of an integration test using supertest.
Edit:
So this is a little experimental test I was playing around with to test that the routing is correct. I'm using mocha as the test runner and the code example I posted in my original code.
// standard library
var assert = require("assert");
// in app objects
var router = require('./router.js');
var service = require('./service.js');
describe("routing tests", function() {
it("test register routing, POST", function*(done) {
// arrange
var unsecured = router.unsecured;
var path = '/account/register';
var httpMethod = 'POST';
var expected = service.register.toString();
var actual;
// act
for (var i = 0; i < unsecured.stack.length; i++)
{
var pathMatch = unsecured.stack[i].path === path;
var methodMatch = unsecured.stack[i].methods.indexOf(httpMethod) >= 0;
if (pathMatch && methodMatch)
{
actual = unsecured.stack[i].middleware.toString();
break;
}
}
// assert
try {
assert.equal(expected, actual);
done();
} catch(err) {
done(err);
}
});
});
There is probably a neater way of doing this (and a more modular way for testing multiple paths) but as I said this is just a basic example to verify the routing is calling the correct service. What I'm doing is delving into the koa-router object to verify what path is bound to what service code depending on the HTTP method (e.g. POST, GET, etc).
If you have your routing and your services in modules this test completely avoids dealing with the main koa app. Although technically this test spans multiple units (the routing and the service code) so it would technically be an integration test but it does mean you don't go near app.listen() which is what you didn't want to call in your tests.

Resources