【问题标题】:unit testing async-waterfall using mocha使用 mocha 对异步瀑布进行单元测试
【发布时间】:2016-02-21 02:01:00
【问题描述】:

我正在使用 Mocha 作为我的 node.js 应用程序的测试框架。

我有一个使用异步瀑布节点模块的现有模块。我正在尝试为它编写一个单元测试用例。我无法为数组中的第二个函数编写测试用例。关于如何将一个函数的结果传递给数组中的下一个函数的任何提示 var async = require('async');

module.exports.resetPassword = function(req,res,next){
 async.waterfall([
  function(done){
    var token = do something;
    done(err,token);
  },
   function(token,done){
       //do some stuff
     res.status(200).send('success');
   },
    ]function(err){ 
     //send failure response
     });
};

【问题讨论】:

  • 嗨,我不太明白这个问题。无论第一种方法如何,您是否都在尝试测试第二种瀑布方法?你能改变方法还是给它?
  • 嗨,在第一个函数中,我能够获得一些令牌价值。我需要将此令牌传递给第二个函数。我无法更改该方法,因为它是现有方法
  • 我面临的问题是控件进入异步瀑布中的第一个函数,但是在调用done(err,token)之后,控件没有进入第二个函数(token,完成)

标签: node.js unit-testing asynchronous tdd mocha.js


【解决方案1】:

我想我现在明白了这个问题。 在您的测试中 - 您执行以下行:

user.resetPassword(request,response,next);

紧随其后 - 行:

cryptoStub.restore();

问题是 - async.waterfall 将启动第一个方法,但在运行第二个方法之前,它将运行单元测试的下一行,因此您看不到下一个方法。解决它的代码如下:

user.resetPassword(request,response,function(err) {
    cryptoStub.restore();
    done();
});

好看吗?

【讨论】:

  • 嗨吉拉德,感谢您的回答。您的解决方案有效:)。由于我是 node.js 的新手,所以我花了一点时间来理解。它实际上对我有用,而无需在 resetPassword 中编写 crytoStub,restore() 。我没有注意到的是,在对 done() 的调用执行之后,调用最终转到了第二个函数。来自 .NET MS 测试背景,我曾期望在执行 user.resetPassword() 行时调用第二个函数,而不是在控制到达 crypto.restore() 之后。需要更多地研究异步单元测试。感谢您的帮助
【解决方案2】:

我的代码如下。我的问题是为此方法编写单元测试用例。我正在使用 mocha 和 sinon 进行存根。我写的单元测试是

单元测试

  it("Should return an error if there is an error in retrieving the user details from the db",function(done)
{
    request={
        body:{
            email:'test@test.com'

        }
    };

    var expectedMessageFromCrypto = '12121212121';
    var cryptoStub = sinon.stub(crypto, "randomBytes",function(err,callback){
        callback(null,expectedMessageFromCrypto);
    });

    user.resetPassword(request,response,next);

    cryptoStub.restore();
    done();
});
});

resetPassword 模块

methods.exports.resetPassword = function (req, res, next) {
var token = null;
async.waterfall([
    function (done) {
        crypto.randomBytes(16, function (err, buf) {
        if(err){
            return res.status(400);
        }
        else{
            token = buf.toString('hex');
        }
        done(err, token);
        });
    },
    function (token, done) {            
    var user = getUserInformation(req.body.email);
        sendEmail(user, done);
    }
], function (err) {
    if (err) {
        logger.error('error in sending confirmation mail');
        return next(err);
    }        
    res.status(200).send('success');
});
};

【讨论】:

  • 您的代码实际上看起来应该可以工作。我也在我的电脑上尝试了它,稍作改动,它进入了第二种方法。也许它卡在 getUserInformation 上?你可以在不同的位置添加console.log,这样你就可以知道卡在哪里了?
  • 我添加了一个 console.log 并获得了预期值。对我来说,当我从单元测试代码进行调试时,控件没有输入 getUserInformation。在跨越涉及加密的功能之后,它就从整个模块中出来了。我在单元测试中遗漏了什么吗?当我调试我的产品代码时,它运行良好。不确定我的单元测试用例中是否遗漏任何内容
  • 我发布了另一个答案
猜你喜欢
  • 2015-04-14
  • 1970-01-01
  • 2016-09-21
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 2016-04-05
  • 1970-01-01
相关资源
最近更新 更多