【问题标题】:How can I execute async Mocha tests (NodeJS) in order?如何按顺序执行异步 Mocha 测试(NodeJS)?
【发布时间】:2012-04-01 22:43:16
【问题描述】:

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

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

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

我该怎么做?

【问题讨论】:

    标签: javascript node.js mocha.js


    【解决方案1】:

    使用mocha-steps

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

    【讨论】:

    • 相同。我遇到了同样的问题,这对我有帮助。
    • 我查看了代码,它似乎没有提供任何顺序保证,只是在第一次检测到故障时停止。
    • 现在是 2021 年,这对我有帮助。谢谢!!
    【解决方案2】:

    我想用我们的应用程序解决同样的问题,但accepted answer 对我们来说效果不佳。尤其是在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();
        } );
      } );
    } );
    

    【讨论】:

    • 我最好将第二行和第三行代码(application = ...bootPromise = ...)放在顶层套件(“应用程序”)的异步before 块中。否则,此代码引发的任何异常都不会被正确捕获和报告,更糟糕的是,会阻止所有剩余测试的执行。
    【解决方案3】:

    重点不在于“结构化代码按照您构建它的顺序运行”(惊奇!)——而是正如@chrisdew 所建议的那样,异步测试的返回顺序不能得到保证。重申一下这个问题 - (同步执行)链更下游的测试不能保证由异步测试设置的所需条件将在它们运行时准备好。

    因此,如果您需要在第一次测试中设置某些条件(例如登录令牌或类似的),您必须使用像 before() 这样的钩子来测试这些条件是否已设置,然后再继续。

    将依赖测试包装在一个块中并在它们上运行 async 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
      });
    
    })
    

    【讨论】:

    • 如果 before 回调被锁定在 while 循环中,someCondition 将如何改变?!这不是 JavaScript 的工作方式。
    • 您的问题的答案在评论第 3 行:“..your Async tests setting conditions go up here”。具体来说:异步,设置条件,范围在describe() 之外,在before() 之前实例化。您关于 Javascript 不能以这种方式工作的后一个断言是错误的。
    • 当您的代码被卡在反复检查 !someCondition 一遍又一遍时,您的其他代码都无法运行。 (与事件/计时器相关的所有其他回调将被阻止执行。)唯一可行的方法是在循环开始之前将 someCondition 设置为 true ——否则它将挂起。试试看。
    • 事实上,Mocha 中的异步测试确实按照声明的顺序运行(并且 async before 挂钩在第一个测试之前运行,无论是异步的还是同步的)。唯一需要轮询机制的情况是设置异步条件的代码不接受回调并且不返回承诺。
    【解决方案4】:

    我对您在我使用时所写的内容感到惊讶。我将 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 问题跟踪器中的 this issue。根据它,测试是同步运行的。

    【讨论】:

    • 这仅表明有序代码按顺序运行。这不是偶然发生的。这就是“它的工作原理”。
    • 这表明有序的异步测试按顺序运行:end1 将始终出现在start2 之前。为了简化示例,您可以将第一个测试的内容替换为setTimeout(done, 1000)。如果您将 before 钩子替换为异步钩子,它将始终在第一次测试之前运行。据我了解,这正是主题启动者感兴趣的行为,而且这种行为是默认的,也是唯一的,至少现在是这样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-24
    • 2012-05-19
    • 2019-08-27
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多