如何按顺序执行异步Mocha测试(NodeJS)?

时间:2012-03-16 11:28:12

标签: javascript node.js mocha

这个问题与NodeJS的Mocha测试框架有关。

默认行为似乎是启动所有测试,然后在进入时处理异步回调。

当运行异步测试时,我想在之前运行每个测试之前的异步部分。

我该怎么做?

4 个答案:

答案 0 :(得分:35)

关键不在于“结构化代码以你构造它的顺序运行”(令人惊讶!) - 而是正如@chrisdew所说,异步测试的返回顺序无法保证。重述问题 - 在(同步执行)链下面的测试无法保证由异步测试设置的所需条件将在它们运行时准备就绪。

因此,如果您要求在第一次测试中设置某些条件(如登录令牌或类似),则必须使用before()之类的钩子来测试在继续之前设置这些条件。

将依赖测试包装在一个块中并对它们运行异步 before挂钩(注意前面块中的'done'):

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

})

答案 1 :(得分:8)

我对你用的东西感到惊讶。我使用mocha和bdd样式测试(describe / it),然后在我的测试中添加了一些console.log来查看你的声明是否符合我的情况,但看起来他们没有。

这是我用来查看“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问题跟踪器中查看this issue。根据它,测试同步进行。

答案 2 :(得分:6)

使用mocha-steps

它会使测试保持顺序,无论它们是否异步(即您的done函数仍然完全正常工作)。它是it的直接替代品,而是使用step

答案 3 :(得分:5)

我想用我们的应用程序解决同样的问题,但accepted answer对我们来说并不好用。特别是someCondition永远不会成真。

我们在应用程序中使用promises,这使得很容易相应地构建测试。然而,密钥仍然是通过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();
    } );
  } );
} );