2013-07-19 70 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

相關問題