2012-03-16 69 views
42

這個問題涉及到NodeJS的Mocha測試框架。如何按順序執行異步摩卡測試(NodeJS)?

默認的行爲似乎是啓動所有的測試,然後處理異步回調,因爲他們進來,

當運行異步測試,我想的異步部分後運行每個測試一個之前被稱爲。

我該怎麼做?

回答

30

重點不在於「結構化代碼按照您構建它的順序運行」(令人驚歎!) - 而是如@ chrisdew所示,異步測試的返回訂單無法得到保證。爲了重新說明問題 - 進一步在(同步執行)鏈下的測試不能保證由異步測試設置的所需條件將在他們運行時做好準備。

因此,如果您要求在第一次測試中設置某些條件(如登錄令牌或類似條件),則必須使用鉤子(如before())來測試在繼續之前設置的條件。

裹在一個塊中的相關測試和運行它們的異步before鉤(注意「做」的前擋):

var someCondition = false 

// ... your Async tests setting conditions go up here... 

describe('is dependent on someCondition', function(){ 

    // Polls `someCondition` every 1s 
    var check = function(done) { 
    if (someCondition) done(); 
    else setTimeout(function(){ check(done) }, 1000); 
    } 

    before(function(done){ 
    check(done); 
    }); 

    it('should get here ONLY once someCondition is true', function(){ 
    // Only gets here once `someCondition` is satisfied 
    }); 

}) 
+0

如果before回調在while循環中被鎖定,'someCondition'會如何改變?!這不是JavaScript的工作方式。 – natevw 2013-06-03 19:50:08

+0

你的問題的答案在評論第3行:「..你的異步測試設置條件上升到這裏」。具體來說就是:異步,設置條件,範圍在'before()'之前實例化的'describe()'之外。你後來對Javascript的斷言不是以這種方式工作是錯誤的。 – papercowboy 2013-06-04 22:31:14

+0

當您的代碼被反覆檢查!someCondition時,您的其他代碼都無法運行。 (與事件/定時器相關的所有其他回調將被阻止執行。)這將工作的唯一方法是,如果someCondition在循環開始之前設置爲true,否則它將掛起。嘗試一下。 – natevw 2013-06-05 05:46:51

7

我很驚訝你寫的,因爲我使用。我用bdd風格測試(描述/它)來使用摩卡,並且只是在我的測試中添加了一些console.logs,以查看您的聲明是否適合我的情況,但看起來他們沒有。

以下是我用來查看「end1」和「start1」順序的代碼片段。他們被妥善訂購。

describe('Characters start a work', function(){ 
    before(function(){ 
     sinon.stub(statusapp, 'create_message'); 
    }); 
    after(function(){ 
     statusapp.create_message.restore(); 
    }); 
    it('creates the events and sends out a message', function(done){ 
     draftwork.start_job(function(err, work){ 
     statusapp.create_message.callCount.should.equal(1); 
     draftwork.get('events').length.should.equal(
      statusapp.module('jobs').Jobs.get(draftwork.get('job_id')).get('nbr_events') 
     ); 
     console.log('end1'); 
     done(); 
     }); 
    }); 
    it('triggers work:start event', function(done){ 
     console.log('start2'); 
     statusapp.app.bind('work:start', function(work){ 
     work.id.should.equal(draftwork.id); 
     statusapp.app.off('work:start'); 
     done(); 
     }); 

當然,這可能是偶然發生過,但我有很多的測試,如果他們將並行運行,我一定會有競爭條件,我沒有。請參閱this issue。根據它,測試是同步運行的。

+0

這隻顯示有序代碼按順序運行。這不是偶然發生的。這是「它是如何工作的」。 – papercowboy 2012-10-19 22:55:16

+0

這表明按順序運行異步測試:'end1'將始終發生在'start2'之前。爲了簡化示例,您可以用'setTimeout(done,1000)'替換第一個測試的內容。如果用異步代碼替換'before'鉤子,它會在第一次測試之前始終運行。據我所知,這正是主題啓動者感興趣的行爲,並且這種行爲是默認行爲,也是唯一的行爲,至少到目前爲止。 – skozin 2014-09-21 02:09:33

5

我想解決這個同樣的問題與我們的應用,但accepted answer並不適合我們。特別是在someCondition永遠不會是真的。

我們在我們的應用程序中使用承諾,這些使得它很容易相應地構建測試。然而,關鍵的還是通過before鉤到延遲執行:

var assert = require("assert"); 

describe("Application", function() { 
    var application = require(__dirname + "/../app.js"); 
    var bootPromise = application.boot(); 

    describe("#boot()", function() { 
    it("should start without errors", function() { 
     return bootPromise; 
    }); 
    }); 

    describe("#shutdown()", function() { 
    before(function() { 
     return bootPromise; 
    }); 

    it("should be able to shut down cleanly", function() { 
     return application.shutdown(); 
    }); 
    }); 
}); 
+3

我最好將第二行和第三行代碼('application = ...'和'bootPromise = ...')放在頂級套件(「應用程序」)中的async'before'塊之內。否則,從該代碼拋出的任何異常都不會被捕獲並正確報告,更糟糕的是,將阻止執行所有剩餘的測試。 – skozin 2014-09-21 01:59:38

4

使用mocha-steps

它使測試順序,不管它們是異步與否(即你done功能仍能正常工作,正是因爲他們做了)。它是it的直接替代品,而不是您使用的step

+0

這是爲什麼這個投票? – 2016-11-21 18:20:36

+1

@JackMurphy很好的問題。 – WiR3D 2016-11-24 12:18:58

+0

相同。我有同樣的問題,這幫助了我。 – hrishioa 2016-12-14 01:47:45