如何使用Mocha对node.js函数进行单元测试?

时间:2015-05-14 01:13:10

标签: node.js unit-testing mocking mocha

我正在尝试测试一个看起来像这样的函数:

function sendVerifySms(patientId, data) {
    var smsNumber = data.smsNumber;
    var verifyCode = ((Math.random() * 1000000) | 0).toString();

    var sql = "UPDATE [patient]";
    sql += " SET phone_sms_verify_code = '" + verifyCode + "',";
    // verification must take place within a one hour period
    sql += " phone_sms_verify_code_expire = '" + moment.utc().add(1, 'hour').formatSqlDatetime() + "',";
    sql += " phone_sms_verified = 0,"
    sql += " phone_sms = '" + escapeSql(smsNumber) + "'";
    sql += " WHERE id = " + escapeSql(patientId.toString());

    return sqlServer.query(sql).then(function(result) {
        twilioClient.sendMessage({
            to: smsNumber,
            from: twilioUser.verifyNumber,
            body: verifyCode
        }).then(function(res) {
            console.log('sent verification');
            return verifyCode;
        }).fail(function(err) {
            console.log('error sending verification');
            console.log(err);
            return err;
        });
    }).fail(function(err) {
        console.log(err);
        return err;
    });
}

够简单吧?好吧,首先我需要确定我正在测试的是什么。

  1. sql命令与给定data
  2. 的格式匹配
  3. 已调用twilioClient.sendMessage
  4. 到目前为止,这是我的测试内容:

    var should = require('should');
    var methods;
    var mockery = require('mockery');
    var sinon = require('sinon');
    
    describe('RPC Methods', function() {
        before(function() {
            mockery.enable();
            mockery.registerMock('msnodesql', {
                open: function() {
                    return true;
                }
            });
    
            mockery.registerMock('../../db/sqlserver', {
                query: function() {
                    return {
                        then: function() {
                            return true;
                        }
                    }
                }
            });
    
            methods = require('../../../rpc/methods');
        });
    
        it('should send a verify SMS', function() {
            var data = {
    
            }
    
            methods.sendVerifySms(1, data);
            should(1).equal(1);
        });
    });
    

    所以现在我有点迷失在这里。我有大量的require,因为我想隔离我的各个函数进行测试,我认为像mockery这样的东西会起作用。我从哪里开始?

    如果有任何不清楚的地方,请发表评论,我会澄清。

    谢谢!

1 个答案:

答案 0 :(得分:1)

使用mocha测试,您有一个可选的done回调,可以更轻松地测试异步函数,如下所示:

it('should send a verify SMS', function(done) {
    var data = {};
    var code = 1;
    methods.sendVerifySms(code, data)
        .then(function(actualCode) {
            should(actualCode).equal(code);
            done();
        });
});

我也会对您正在测试的异步功能提供一些反馈。首先,我要说你不必按照自己的方式嵌套承诺链,在这种情况下,它可能更好,你没有。如果您只是在promise回调中返回一个promise,则可以将它链接到同一级别,如下所示:

return sqlServer.query(sql).then(function(result) {
    return twilioClient.sendMessage({
        to: smsNumber,
        from: twilioUser.verifyNumber,
        body: verifyCode
    });
}).then(function(res) {
    console.log('sent verification');
    return verifyCode;
}).fail(function(err) {
    console.log(err);
    throw err;
});

其次,在你只是返回错误之前的错误处理程序中。这可能是一个坏主意,因为它告诉消费者你的承诺,一切都是笨拙的,他们应该这样做。另一方面,抛出错误将允许该消费者在他们自己的.fail块中处理他们想要的错误。