首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >有没有办法让Chai使用异步Mocha测试?

有没有办法让Chai使用异步Mocha测试?
EN

Stack Overflow用户
提问于 2012-06-28 06:43:58
回答 13查看 52.9K关注 0票数 81

我正在使用Browser Runner在Mocha中运行一些异步测试,并尝试使用Chai的expect风格断言:

代码语言:javascript
复制
window.expect = chai.expect;
describe('my test', function() {
  it('should do something', function (done) {
    setTimeout(function () {
      expect(true).to.equal(false);
    }, 100);
  }
}

这并没有给出正常的失败断言消息,相反,我得到:

代码语言:javascript
复制
Error: the string "Uncaught AssertionError: expected true to equal false" was thrown, throw an Error :)
    at Runner.fail (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3475:11)
    at Runner.uncaught (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3748:8)
    at uncaught (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3778:10)

所以很明显它捕捉到了错误,只是没有正确地显示出来。你知道该怎么做吗?我想我可以用一个错误对象来调用"done“,但这样我就失去了像Chai这样的东西的优雅,它变得非常笨拙……

EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2013-03-05 02:07:24

异步测试在失败的expect()操作上生成一个异常,it()无法捕获该异常,因为该异常被抛出在it()的作用域之外。

显示的捕获异常是使用node下的process.on('uncaughtException')或浏览器中的window.onerror()捕获的。

要解决此问题,您需要在setTimeout()调用的异步函数中捕获异常,以便以异常作为第一个参数调用done()。您还需要调用不带参数的done()来表示成功,否则mocha将报告一个超时错误,因为您的测试函数永远不会发出已完成的信号:

代码语言:javascript
复制
window.expect = chai.expect;

describe( 'my test', function() {
  it( 'should do something', function ( done ) {
    // done() is provided by it() to indicate asynchronous completion
    // call done() with no parameter to indicate that it() is done() and successful
    // or with an error to indicate that it() failed
    setTimeout( function () {
      // Called from the event loop, not it()
      // So only the event loop could capture uncaught exceptions from here
      try {
        expect( true ).to.equal( false );
        done(); // success: call done with no parameter to indicate that it() is done()
      } catch( e ) {
        done( e ); // failure: call done with an error Object to indicate that it() failed
      }
    }, 100 );
    // returns immediately after setting timeout
    // so it() can no longer catch exception happening asynchronously
  }
}

在所有测试用例上这样做既烦人又不干练,因此您可能希望提供一个函数来为您完成此操作。让我们将此函数称为check()

代码语言:javascript
复制
function check( done, f ) {
  try {
    f();
    done();
  } catch( e ) {
    done( e );
  }
}

使用check(),您现在可以重写异步测试,如下所示:

代码语言:javascript
复制
window.expect = chai.expect;

describe( 'my test', function() {
  it( 'should do something', function( done ) {
    setTimeout( function () {
      check( done, function() {
        expect( true ).to.equal( false );
      } );
    }, 100 );
  }
}
票数 97
EN

Stack Overflow用户

发布于 2015-12-19 11:33:53

以下是我对ES6/ES2015 promises和ES7/ES2016 async/await的通过测试。希望这篇文章能为任何研究这个话题的人提供一个很好的更新答案:

代码语言:javascript
复制
import { expect } from 'chai'

describe('Mocha', () => {
  it('works synchronously', () => {
    expect(true).to.equal(true)
  })

  it('works ansyncronously', done => {
    setTimeout(() => {
      expect(true).to.equal(true)
      done()
    }, 4)
  })

  it('throws errors synchronously', () => {
    return true
    throw new Error('it works')
  })

  it('throws errors ansyncronously', done => {
    setTimeout(() => {
      return done()
      done(new Error('it works'))
    }, 4)
  })

  it('uses promises', () => {
    var testPromise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('Hello')
      }, 4)
    })

    testPromise.then(result => {
      expect(result).to.equal('Hello')
    }, reason => {
      throw new Error(reason)
    })
  })

  it('uses es7 async/await', async (done) => {
    const testPromise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('Hello')
      }, 4)
    })

    try {
      const result = await testPromise
      expect(result).to.equal('Hello')
      done()
    } catch(err) {
      done(err)
    }
  })

  /*
  *  Higher-order function for use with async/await (last test)
  */
  const mochaAsync = fn => {
    return async (done) => {
      try {
        await fn()
        done()
      } catch (err) {
        done(err)
      }
    }
  }

  it('uses a higher order function wrap around async', mochaAsync(async () => {
    const testPromise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('Hello')
      }, 4)
    })

    expect(await testPromise).to.equal('Hello')
  }))
})
票数 20
EN

Stack Overflow用户

发布于 2014-02-10 23:22:35

如果你喜欢promised,试试Chai as Promised + Q,它允许这样的东西:

代码语言:javascript
复制
doSomethingAsync().should.eventually.equal("foo").notify(done);
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11235815

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档