web-dev-qa-db-ja.com

非同期Mochaテスト(NodeJS)を順番に実行するにはどうすればよいですか?

この質問は、NodeJSのMochaテストフレームワークに関連しています。

デフォルトの動作は、すべてのテストを開始してから、非同期コールバックが処理されると処理するようです。

非同期テストを実行する場合、各テストを実行しますafter前の非同期部分が呼び出されました。

これどうやってするの?

50
fadedbee

ポイントは、「構造化されたコードが構造化された順序で実行される」ほどではありません(驚く!)-@chrisdewが示唆するように、非同期テストの戻り順序は保証できません。問題を再現するには同期実行)チェーンのさらに下にあるテスト---(保証はできません非同期テストで設定された必要な条件は、実行時に準備が整います。

したがって、最初のテストで特定の条件(ログイントークンなど)を設定する必要がある場合は、続行する前にこれらの条件を設定するbefore()などのフックを使用する必要があります。

ブロックで依存テストをラップし、それらに対してasyncbeforeフックを実行します(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
  });

})
35
papercowboy

私が使っているのにあなたが書いたことに驚いています。私はmochaをbddスタイルのテスト(describe/it)で使用し、テストに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();
      });

もちろん、これも偶然に起こった可能性がありますが、私にはたくさんのテストがあり、それらが並行して実行される場合、私は間違いなく競合状態になります。

Mocha issue trackerの this issue も参照してください。それによると、テストは同期的に実行されます。

9
Akasha

mocha-steps を使用します

テストが非同期であるかどうかに関係なく、テストを連続的に実行します(つまり、done関数はまだ正確に機能します)。これはitの直接の置き換えであり、代わりにstepを使用します

6
WiR3D

私たちのアプリケーションでこれと同じ問題を解決したかったのですが、 受け入れられた答え はうまくいきませんでした。特にsomeConditionで真になることはありません。

アプリケーションでpromiseを使用します。これにより、テストを適切に構造化することが非常に簡単になりました。ただし、重要な点は、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();
    } );
  } );
} );
5
Der Hochstapler