Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS - How to test index.js without module.exports

I'm testing my NodeJs project using Mocha and I have a file, index.js that is the main file without module.exports that is run like a CLI

index.js

// CLI tools
var bluebird  = require('bluebird');
var gigatool  = require('./lib/gigatool');
var debug     = require('debug')('index');
var size      = 20;

var page      = process.env.BATCH;
var startDate = process.env.START;
var dataDir   = process.env.DATADIR;
debug(page, startDate, dataDir);

// requires parameters
if (!process.env.BATCH) {
  throw new Error('BATCH environment variable is needed');
}

tool = gigatool(size, page, dataDir);

bluebird.all([tool.clean(startDate), tool.continuous()])
  .finally(function(){
    process.exit(0);
  });

test.js

'use strict';

var chai   = require('chai');
var fs     = require('fs');
var noop   = require('lodash.noop');
var rimraf = require('rimraf');
var async  = require('async');
var rimraf = require('rimraf');

var expect = chai.expect;

describe.only('Integration', function() {
  var dataDir = './countries';
  var path = dataDir + '/Albania';

  describe('clean run', function() {
    this.timeout(10000);
    before(function() {
      process.env.BATCH = 1;
      process.env.DEBUG = '*';
      require('../../index');
    });

    after(function(done) {
      // rimraf(dataDir, done);
    });
  });
});

if I run require('./index'), it will run the module and then continue to move forward, how can i wait for it to end before i run test cases?

Note: It is calling some apis

like image 572
eugene Avatar asked Dec 24 '14 09:12

eugene


People also ask

Can you write a node js test without an external library?

js unique: you can write applications in Node. js without the use of external libraries.

Is it possible to write tests in node JS?

To create unit tests for a Node.Create a separate file for your tests in the project's folder. A unit test for the multiplication function from the demo Node. js application looks like as shown below. This code is in a file called multiplication.


2 Answers

You need to test your whole application at once, this is still testing but hardly "unit" testing unless your code is a unit ("the unix way"). For this reason your code should start with:

var Promise= require("bluebird");
var exec= Promise.promisify(require("child_process").exec);

var run = function(args){
    return exec("node", ["../../index.js"].concat(args)).get("stdout");
};

Which would make your tests test the actual inputs on the file:

describe('your code', function() {
    it('should work with params a,b', function(){
        return run(['a','b']).then(function(out){ // note the Mocha promise syntax
           assert.equal(out, 'your expected stdout');
        });
    });
});
like image 185
Benjamin Gruenbaum Avatar answered Oct 22 '22 07:10

Benjamin Gruenbaum


Unfortunately, there is no way to unit test individual aspects of a CLI Node script as you have it. Instead, what I've done in the past is have conditional execution based on whether the script was used via require or called from the command line:

// index.js

var foo = require('foo');
var bar = require('bar');
// ...

// determine if this script is being required as a module or is CLI
var IS_EXECUTING = (require.main === module);

var methods = {
    init: function(args) {
        methods.auditArgs(args);
        methods.doSomeStuff(arg1, arg2);
        methods.doOtherStuff();
    },

    auditArgs: function(args) {/* ... */},
    doSomeStuff: function(arg1, arg2) {/* ... */},

    // ...
};

// At the bottom we either begin execution or return a function which can 
// be called in a test harness when ready...
if (IS_EXECUTING) {

    methods.init(process.argv);

} else {
    module.exports = function (mockMethods) {
        // you could have some code here to mock out provided methods
        // for example:
        methods.auditArgs = mockMethods.auditArgs || methods.auditArgs;

        // then return the "API" for this script...
        return methods;
    };
}

In your test harness then you would simply require the file and when ready, use it like you would any other module. But when called from the command line the code will just execute normally:

// in test.js
'use strict';

var chai        = require('chai');
// ...
var appFactory  = require('index');

var expect = chai.expect;

describe('initialization', function() {
    var app;
    beforeEach(function() {
        app = appFactory({
            auditArgs = chai.spy(function() { });
            // other mock method implementations, spies, etc
        });
    });

    it('should call necessary methods on init', function() {
        expect(app.auditArgs).to.have.been.called(1);
        // ...
    });
});
like image 38
Jordan Kasper Avatar answered Oct 22 '22 07:10

Jordan Kasper