【问题标题】:mocha with nodejs assert hangs/timeouts for assert(false) instead of error带有nodejs断言的摩卡挂起/超时断言(假)而不是错误
【发布时间】:2015-01-02 10:06:07
【问题描述】:

我有这种摩卡测试:

describe 'sabah', →
    beforeEach →
        @sabahStrategy = _.filter(@strats, { name: 'sabah2' })[0]
            .strat

    it 'article list should be populated', (done) →
        @timeout 10000
        strat = new @sabahStrategy()
        articles = strat.getArticleStream('barlas')
        articles.take(2).toArray( (result)→
            _.each(result, (articleList) →

                // I make the assertions here
                // assert(false)
                assert(articleList.length > 1)
            )
            done()
        )

问题是,每当我执行assert(false) 时,测试都会挂起直到超时,而不是给出断言错误,为什么?

编辑:

例如,如果我有这两个测试

    it 'assert false', (done) →
        assert(false)
        done()

    it 'article link stream should be populated', (done) →
        @timeout 20000
        articles = @sabahStrategy.articleLinkStream('barlas')
        articles.pull((err, result)→
            console.log('here')
            assert(false)
            console.log('after')
            assert(!err)
            assert(result.length > 1);
            _.each(result, (articleList) →
                assert(articleList.link)
            )
            done()
        )

第一个,按预期给出断言错误,第二个,记录here,并挂在assert(false),因此永远不会记录after。它与articles 是一个流有关,并且断言在pull 回调中,这是来自highland.js API

已解决编辑

所以根据 Paul 的说法,我用这段代码解决了这个问题:

    it 'article stream should be populated', (done) →
        @timeout 30000
        articles = @sabahStrategy.articleStream('barlas')

        articles.pull((err, result) →
            try
                # assert false properly throws now.
                assert(false)
                assert(!err)
                assert(result.length == 1)
                assert(result[0].body)
                assert(result[0].title || result[0].title2)
                done()
            catch e
                done(e)
        )

编辑2

我已经制作了问题的简化版本:

h = require('highland')
Q = require('q')

describe 'testasynchigh', →
    beforeEach →
        @deferred = Q.defer()
        setTimeout((→
            @deferred.resolve(1)
        ).bind(this), 50)


    it 'should throw', (done) →
        s = h(@deferred.promise);
        s.pull((err, result) →
            console.log result
            assert false
            done()
        )

我看到你的版本确实有效@Louis,但如果你在混合中加入承诺,mocha 无法解决问题,所以它会在这个例子中挂起。还可以尝试注释掉assert false 并查看它是否通过。

Louis,我希望我能引起你的注意,你能解释一下这个问题吗,try catch 看起来确实很丑,我希望你能找到一个合理的解决方案。

【问题讨论】:

    标签: javascript node.js tdd mocha.js highland.js


    【解决方案1】:

    因为这就是你告诉它你想做的事情,当你添加“完成”回调时。

    实际执行此测试的方法是在断言失败时调用return done(err),其中 err 是您要报告的任何字符串或错误对象。

    首先,当你的断言失败时,程序会抛出一个异常并且永远不会到达done(),这就是你没有看到 done 被调用的原因。这就是断言应该如何工作,但是由于您处于异步测试中,结果是回调永远不会触发,这就是您达到超时的原因。

    其次,正如我最初的回答所说,err 是您想从测试中发出的任何错误。它可以是字符串错误消息或完整的错误对象子类。您创建它,然后将其传递给 done() 以指示测试失败。

    在异步测试中构建代码的更好方法是将测试用作简单的布尔值,而不是断言。如果您真的想使用断言,请将其包装在 try..catch 中。这里有几个例子:

    if(err) return done(err); // in this case, err is defined as part of the parent callback signature that you have in your code already.
    
    if(result.length < 1) return done('Result was empty!'); 
    

    最后,如果你真的想assert,那么你可以:

    try{
      assert(!err);
    }catch(e){
      return done(e);
    }
    

    我调用return done(err) 而不是done(err),因为它会阻止其余代码执行,这通常是您想要的。

    【讨论】:

    • 我也写了两年多的 Mocha 代码,通常您不需要像您在此处的答案中显示的那样捕获异常。很可能是highland.js 正在吞噬异常,或者它在处理回调中的异常方面有一些特殊性。但总的来说,Mocha 非常有能力检测异常,无论是同步的还是异步的。只需运行it("test", function (done) { setTimeout(function () { throw new Error(); }, 100); });done 未被调用,这不是错误。)` Mocha 将毫无问题地检测到异常。
    • @Louis,你的意思是像这里描述的那样吞咽github.com/caolan/highland/issues/121,你认为这可能是问题吗?
    • @user3995789 是的,我认为这就是问题所在。我已经用 RSVP(另一个 promise 库)尝试了你最新的 sn-p,并得到了与 Q 相同的结果。我也尝试过使用 Highland 的 .errors( 调用,但我没有得到任何结果。
    • @Lous 那么我们该怎么办?你认为try catch 是现在要走的路吗?或者我应该删除asserts。
    【解决方案2】:

    对于遇到相同问题的任何人:您应确保即使在断言失败后也调用 done(),如以下代码所示:

    try {
      // your asserts go here
      done();
    } catch (e) {
      done(e);
    }
    

    【讨论】:

      【解决方案3】:

      当我使用 Highland.js 进行超级简单的测试时,Mocha 可以毫无问题地捕获失败的断言:

      var _ = require("highland");
      var fs = require("fs");
      var assert = require("assert");
      
      describe("test", function () {
          it("test", function (done) {
              var s = _([1, 2, 3, 4]);
              s.pull(function (err, result) {
                  console.log(result);
                  assert(false);
                  done();
              });
          });
      });
      

      这表明您的示例中的问题不是 Mocha,也不是 Highland.js。如果 articleLinkStream 对象(或 articleSream;它似乎从 sn-p 更改为 sn-p)是自定义代码,那么该代码可能有问题并且实际上会吞下异常而不是让它们向上移动。

      【讨论】:

      • 请参阅Edit2
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多