猫鼬承诺在某些条件下无法解决

Posted

技术标签:

【中文标题】猫鼬承诺在某些条件下无法解决【英文标题】:Mongoose promise not resolving under certain conditions 【发布时间】:2014-08-07 11:55:21 【问题描述】:

我有以下代码,我正在尝试编写使用 mocha 的单元测试。在某些情况下,这按预期工作,但在其他情况下,承诺似乎永远不会解决。你能帮我解决这个问题吗?

被测代码:

exports.inGroup = (group, user) ->
    return user.groups.indexOf(group) >= 0

##
# A promise returning function that returns the list
# of viewable channels for a user.
##
exports.getUserViewableChannels = (user) ->

    # if admin allow all channels
    if exports.inGroup 'admin', user
        return Channel.find().exec()
    else        
        # otherwise figure out what this user can view
        return Channel.find( txViewAcl:  $in: user.groups  ).exec()

现在,当我测试非管理员用户时,它可以正常工作:

user = new User
    firstname: 'Some'
    surname: 'User'
    email: 'some@user.net'
    groups: [ 'HISP' , 'group2' ]

it "should return channels that a user can view", (done) ->
    promise = authorisation.getUserViewableChannels user
    promise.then (channels) ->
        channels.should.have.length(2)
        done()
    , (err) ->
        done err

但是,当我测试管理员用户时,promise 没有解决:

user3 = new User
    firstname: 'Random'
    surname: 'User'
    email: 'someguy@meh.net'
    groups: [ 'admin' ]

it "should return all channels for viewing if a user is in the admin group", (done) ->
    promise = authorisation.getUserViewableChannels user3
    promise.then (channels) ->
        channels.should.have.length(3)
        done()
    , (err) ->
        done err

在这种情况下,摩卡测试超时:

Error: timeout of 2000ms exceeded

【问题讨论】:

只是一个随机提示:Mocha 在最近的版本中支持开箱即用的 Promise,您可以只返回 Promise,测试将根据其是否履行/拒绝分别通过或失败。 哦,太棒了!谢谢,我不知道。 【参考方案1】:

嗯,这很脏,但是 - 如果断言 channels.should.have.length(2) 失败,就会发生坏事。 that 断言上没有 .catch 处理程序,这意味着承诺将被拒绝。

由于 mpromise(Mongoose 承诺)不具备任何良好的未处理拒绝检测功能,这将导致承诺静默失败,并且由于在这种情况下从未调用过 done,因此 Mocha 不知道该怎么做。我强烈建议使用 Bluebird 而不是 Mongoose 承诺,因为它们都更快(是的,即使使用 Mongoose)并且不会让这样的静默失败发生,并且会为你跟踪它们。

以下使用 Mocha 在最近版本中提供的新承诺语法应该可以工作。

it "should return all channels for viewing if a user is in the admin group", () ->
    promise = authorisation.getUserViewableChannels user3
    promise.then (channels) ->
      channels.should.have.length(3)

【讨论】:

非常感谢,这有帮助。我无法向 Mocha 返回承诺,因为我仍然需要提供断言。我所做的是将 onResolve 函数的主体包装在 try catch 中。这使我能够找出导致断言失败的根本问题。谢谢! @RyanCrichton 如果您改用 Bluebird 承诺,这将永远不会发生。如果我是你,我会调查它,它为我节省了很多时间。很高兴我能帮上忙。

以上是关于猫鼬承诺在某些条件下无法解决的主要内容,如果未能解决你的问题,请参考以下文章

猫鼬承诺和Q承诺

猫鼬批量保存承诺

蓝鸟承诺:循环猫鼬结果

测试时出现“mpromise(猫鼬的默认承诺库)已弃用”错误[重复]

Typescript 应用程序中的“mpromise(猫鼬的默认承诺库)已弃用”

连接完成后承诺不解决