NodeJS - 如何在没有module.exports的情况下测试index.js

时间:2014-12-24 09:32:59

标签: node.js integration-testing mocha bluebird

我正在使用Mocha测试我的NodeJs项目,我有一个文件index.js,它是没有module.exports的主文件,它像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);
    });
  });
});

如果我运行require('./index'),它将运行模块然后继续向前移动,在运行测试用例之前,我该如何等待它结束?

注意:它正在调用一些apis

2 个答案:

答案 0 :(得分:4)

您需要立即测试整个应用程序,这仍然是测试但很难“单元”测试,除非您的代码是一个单元(“unix方式”)。因此,您的代码应该以:

开头
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");
};

这将使您的测试测试文件上的实际输入:

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');
        });
    });
});

答案 1 :(得分:3)

不幸的是,没有办法对CLI节点脚本的各个方面进行单元测试。相反,我过去所做的是根据脚本是通过require使用还是从命令行调用来进行条件执行:

// 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 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);
        // ...
    });
});