1

Problem seems very trivial so I am really embarrassed that I can’t solve it on my own but I did a lot of search on google and stackoverflow and nothing helped me yet. I am developing RESTful server with node.js and I want to test it’s API. Server initialize asynchronously (it needs to connect to db, to request token from another server etc.). So code in my server.js file looks like this:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var MongoClient = require('mongodb').MongoClient;
var bunyan = require('bunyan'); // logger
var routes = require('./routes/folrouter.js');
var TokenGetter = require('./utils/tokengetter');


MongoClient.connect('mongodb://localhost:27017/fol', function (err, db)
{
    if (err)
        throw err;

    global.db = db;
    global.log = bunyan.createLogger({
            name : "folserver",
            src : true,
            serializers: bunyan.stdSerializers,
            streams : [ {
                path : 'folserver.log',
                type : 'file'
            } ]
        });


    global.log.info("folserver starts...");
    var tg = new TokenGetter();
    tg.on("token_received", function(token){
        global.access_token = token;
        global.log.info("access_token received: " + token);
        //TO DO: compression and cache static content
        app.use(express.static(__dirname + '/public'));
        app.use(bodyParser.urlencoded({ extended: true } ));
        app.use(bodyParser.json());
        app.use('/api', routes);
        app.listen(8080);
        console.log('Express server listening on port 8080');
    });
    tg.getToken();

});

//only for tests!!!
module.exports = app;

I defined script actions in my package.json file so I can run tests from command line with “npm test” command:

{
  "name": "folserver",
  "version": "0.0.0",
  "description": "Server side for my app",
  "main": "server.js",
  "dependencies": {
   ...
  },
  "devDependencies": {
    "mocha": "^2.0.1",
    "should": "^4.3.0",
    "supertest": "^0.15.0"
  },
  "scripts": {
    "test": "./node_modules/.bin/mocha   --require should  --reporter spec  --ui bdd  tests/tests.js",
    "start": "server.js"
  },
  "repository": "",
  "author": "PainKiller",
  "private": true
}

And then I have tests.js with following code:

var should = require('should');
var request = require('supertest');
var app  = require('../server.js');
describe("user.js", function () {
    describe("#upsert()", function () {
        it("should insert new user object correctly", function () {
            before(function (done) {
                console.log("before");
                request(app)
                .post('api/user/upsert', user)
                .set('Accept', 'application/json')
                .end(function (error, res) {
                    done();
                });

            });

            after(function (done) {
                //after
                console.log("after");
                done();
            });

        });

        it("should update new user object correctly", function () {
            //Test Goes Here
        });
    });

    describe("#isregistered()", function () {
        it("should return false on id not in db", function () {
            //Test Goes Here
        });

        it("should return true on id in db", function () {
            //Test Goes Here
        });
    });
});

First problem - my app initializes completely after tests starts - I see it with console.log outputs from my app when I am starting “npm test”. And I see my tests passed in console (they do nothing at that point, except first, but it passed too) Second – I’ve never see console.log outputs from my tests in my console – and it’s really freaks me out, may be this code never runs? But if it’s true, how can I see results of my tests in console?

I see two ways to solve it. First – make delay before starting tests, I’ve tried --timeout command with mocha – it doesn’t helped. Till now I can’t find a proper and nice way to stop execution of JS code for a period of time. Second – to emit event with app, and to start tests on that event, but I’ve failed with this way either. And maybe I am wrong with something else, I just didn’t see it, so I appreciate any help and comments. Thanks in advance!

2 Answers 2

1

Call test function with a callback parameter. Mocha will then run this function asynchronously.

EDIT: Just reorganize your hooks in your case.

describe("#upsert()", function () {

    var result;

    before(function (done) {
         console.log("before");
         request(app)
         .post('api/user/upsert', user)
         .set('Accept', 'application/json')
         .end(function (error, res) {

             result = res;
             done();
        });

    });

        after(function (done) {
            //after
            console.log("after");
            done();
        });

    it("should insert new user object correctly", function () {

        // assert "result" object here
    });

    it("should update new user object correctly", function () {
        //Test Goes Here
    });
});

Because you had "before()" inside a non asynchronous function. it() would exit not waiting for before() to finish. Place async preparation function outside or call it() as an asynchronous function itself.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot for help. I am trying to implement your advise, and first thing I saw - all log traces disapeared, and I still can't see console.log from my tests. Can't figure out what does it mean.
And server endpoints still not work I suppose because they aren't initialized
0

So I've finally managed problem with initializing my app before tests. This is final code:

var should = require('should');
var request = require('supertest');
var app = require('../server.js');

//this is root level hook  with setTimeout do the trick
before(function (done) { console.log("before all"); this.timeout(9000); setTimeout(done, 5000); });

describe("user.js", function () {
    describe("#upsert()", function () {
    before(function (done) {
                console.log("before 2");
                this.timeout(5000);
                var user = { test: "test" }
                request(app)
                .post('/api/user/upsert')
                .set('Content-Length', JSON.stringify(user).length)
                .set('Accept', 'application/json')
                .send(user)
                .end(function (error, res) {
                    if (error) throw error;
                    console.log(res);
                    done();
                });
                //done();
            });

        it("should insert new user object correctly", function (done) {
            console.log("it");
            //console.log(app);
            //console.log(global.db);
            done();

        });
        after(function (done) {
            console.log("after");
            done();
        });

        it("should update new user object correctly", function (done) {
            //Test Goes Here
            done();
        });
    });

    describe("#isregistered()", function (done) {
        it("should return false on id not in db", function (done) {
            //Test Goes Here
            done();
        });

        it("should return true on id in db", function (done) {
            //Test Goes Here
            done();
        });
    });
});

Everything works asynchonously and I see all console.logs in the right places.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.