如何构建涉及 promises 和第三方 NPM 模块的 mocha 单元测试?

How can I structure a mocha unit test that involves promises and third party NPM modules?

我要测试的代码是:

exports.hasTokenOrApi = (req, res, next) ->
  if not req.headers?.authorization
    return res.status(403).end()

  new Promise (resolve, reject) ->
    if req.headers.authorization.length is 32
      # We are using an API key
      global.db.User.find
        where:
          api_key: req.headers.authorization
      .then (dbUser) ->
        resolve dbUser.apiDisplay()
    else
      # We are using a redis session
      req.redisSession.getAsync
        app: 'sessions'
        token: req.headers.authorization
      .then (response) ->
        resolve response.d
  .then (user) ->
    if not user.id
      return res.status(403).end()
    req.user = user

    next()
  .catch (err) ->
    next err

这是一个中间件(我正在使用 Express)来捕获各种 API 端点的令牌或 API 密钥。

到目前为止我进行的测试是:

describe 'Authentication Middleware', ->
  mock_res = {}
  before (done) ->
    mock_res =
      status: ->
        @
      end: ->
        @

    global.db =
      User:
        find: ->
          @
        then: ->
          id: 1


    done()

  it 'should return a 403 is no authorization is set in the header', ->
    mock_req = {}
    mock_next = null

    status_spy = sinon.spy mock_res, 'status'
    end_spy = sinon.spy mock_res, 'end'

    authentication.hasTokenOrApi mock_req, mock_res, mock_next
    status_spy.calledWith(403).should.equal true
    end_spy.called.should.equal true

  it.only 'should detect a valid API key', ->
    mock_req =
      headers:
        authorization: 'e16b2ab8d12314bf4efbd6203906ea6c'
    mock_next = sinon.spy()

    authentication.hasTokenOrApi mock_req, mock_res, mock_next
    mock_next.called.should.equal true

第一次测试很好,效果很好,解决了我所有的问题。 第二个不能正常工作。我认为它与承诺有关?我测试我们返回 false,而我想做的是 true

任何帮助将不胜感激!

我会这样做:

it.only 'should detect a valid API key', (done) ->
    mock_req =
      headers:
        authorization: 'e16b2ab8d12314bf4efbd6203906ea6c'

    authentication.hasTokenOrApi mock_req, mock_res, done

如果根本不调用done,测试将超时。如果调用出错,那么Mocha会报错。

回调 next 将被异步调用。您的测试在有机会被调用之前正在检查 mock_next.called 。您可以通过在以下位置编写自己的回调来验证 next 回调是否被调用:

authentication.hasTokenOrApi mock_req, mock_res, err ->
    if err
        done err
    # if the code has entered this callback, and there's no error 
    # that means that the promise has resolved and everything's good... 
    # we can end the test now
    done()