2013-07-19 72 views
5

这里是我的集群快速的应用程序的简化版本:如何使用Mocha测试集群快速应用程序?

/index.js

module.exports = process.env.CODE_COV 
    ? require('./lib-cov/app') 
    : require('./lib/app'); 

/lib/app.js

var cluster = require('cluster'), 
    express = require('express'), 
    app = module.exports = express.createServer(); 

if (cluster.isMaster) { 
    // Considering I have 4 cores. 
    for (var i = 0; i < 4; ++i) { 
     cluster.fork(); 
    } 
} else { 
    // do app configurations, then... 

    // Don't listen to this port if the app is required from a test script. 
    if (!module.parent.parent) { 
     app.listen(8080); 
    } 
} 

/测试/ TEST1 .js

var app = require('../'); 

app.listen(7777); 

// send requests to app, then assert the response. 

问题:

  1. var app = require('../');不会在此群集环境中工作。它应该返回哪个工作应用程序?它是否应该返回群集对象而不是Express应用程序?
  2. 现在,显然在测试脚本中设置端口将不起作用。如何将测试脚本中的端口设置为应用程序集群?
  3. 你会如何发送请求到这个应用程序集群?

我能想到的唯一的办法是有条件地关闭群集功能,如果该应用程序从一个测试脚本(if (module.parent.parent) ...)要求只运行一个应用程序。

任何其他方式与Mocha测试集群快递应用程序?

回答

8

我发布这个问题已经很长时间了。由于没有人回答,我会自己回答这个问题。

我不停的/index.js,因为它是:

module.exports = process.env.CODE_COV 
    ? require('./lib-cov/app') 
    : require('./lib/app'); 

/lib/app.js其开始簇,我已经下面的代码。简而言之,我只在非测试环境中启动群集。在测试环境中,集群未启动,但只有一个应用程序/工作者本身按cluster.isMaster && !module.parent.parent条件中的定义启动。

var cluster = require('cluster'), 
    express = require('express'), 
    app = module.exports = express.createServer(); 

if (cluster.isMaster && !module.parent.parent) { 
    // Considering I have 4 cores. 
    for (var i = 0; i < 4; ++i) { 
     cluster.fork(); 
    } 
} else { 
    // do app configurations, then... 

    // Don't listen to this port if the app is required from a test script. 
    if (!module.parent.parent) { 
     app.listen(8080); 
    } 
} 

在上述情况下!module.parent.parent将作为仅当该应用程序不是由测试脚本开始一个真实对象进行评估。

  1. module是当前/lib/app.js脚本。
  2. module.parent是其母公司/index.js脚本。
  3. module.parent.parentundefined如果应用程序是直接通过node index.js启动的。
  4. module.parent.parent是测试脚本,如果应用程序是通过其中一个脚本启动的。

因此,我可以安全地启动我可以设置自定义端口的脚本。

/test/test1.js

var app = require('../'); 

app.listen(7777); 

// send requests to app, then assert the response. 

在,如果我需要运行在真正的应用程序,即不进行检测的同时,然后我跑node index.js,它会启动集群应用。

0

我喜欢你的解决方案,因为它很简单,但是,在一个像MVC框架节点的环境中,你最终可能会链接最多11次(严重)的module.parent。

我认为一个更好的方法是简单地检查哪个脚本节点开始处理。 process.argv提供节点的命令行参数。 这个数组中的第一项是'node',可执行文件和第二个参数是节点开始执行的文件的路径。这将是index.js在你的情况。

所以不是检查

    module.parent.parent 
          ^ ^  
         (app.js) | 
           (index.js) 

你可以做这样的事情

var starter = process.argv[1].split(path.sep).pop(); 

starterindexindex.js取决于你用什么启动您的服务器。 node index.js VS node index

支票将随后的样子:

if (cluster.isMaster && starter === 'index.js') { 
    cluster.fork(); 
} 

曾在我的环境,我希望这有助于!

+0

这种假设看起来很危险,因为我不例如,如果应用程序永远执行或像守护进程一样执行,那么参数列表将如何表现。 – Eye

+0

你知道参数列表将如何表现。 [process.argv](http://nodejs.org/docs/latest/api/process.html#process_process_argv)将始终包含0:“node”和1:节点正在处理的脚本。 – jbielick

+0

我认为你是一个cpu线程与节点子进程混淆。如果您使用守护进程监视器 (如永远),永远会启动相应的主进程,然后将其委托给不同的分支来运行您的应用程序。如果永久分支启动您的应用程序,它仍然在运行 'node app.js'。这会以'process.argv'作为['node','path/to/app.js']启动一个节点进程。 如果你使用mocha并编写一个测试单元来执行'exec('node app.js')',那么process.argv仍然是'['node','path/to/app.js' ]'。 – jbielick

2

我有这样

if (process.env.NODE_ENV !== 'test') { 
    if (cluster.isMaster) { 
     var numCPUs = require('os').cpus().length; 
     console.log('total cpu cores on this host: ', numCPUs); 
     for (var i = 0; i < numCPUs; i++) { 
      console.log('forking worker...'); 
      cluster.fork(); 
     } 

     cluster.on('online', function(worker) { 
      console.log('Worker ' + worker.process.pid + ' is online.'); 
     }); 
     cluster.on('exit', function(worker, code, signal) { 
      console.log('worker ' + worker.process.pid + ' died.'); 
     }); 
    } else { 
     console.log('Im a worker'); 
     // application code 
     setupServer() 
    } 
} else { 
    // when running tests 
    setupServer(); 
    } 

的一个更简单的方式运行测试时 前只要确保将env设置为testNODE_ENV=test grunt test

相关问题