简体   繁体   中英

How can I unit test node.js functions with Mocha?

I am trying to test a function that looks like:

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;
    });
}

Easy enough, right? Well, first I need to decide what EXACTLY I'm testing for.

  1. That the sql command matches the format given some data
  2. That the twilioClient.sendMessage has been called.

Here is what I have for my test so far:

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);
    });
});

So now I'm a bit lost from here. I have a ton of require and since I want to isolate my individual functions for testing, I figured something like mockery would work. Where do I go from here?

If anything is unclear, please post a comment and I'll clarify.

Thanks!

With mocha tests you have an optional done callback that makes testing async functions easier, like this:

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();
        });
});

I would also have some feedback to offer on the async function you're testing. First I'd say you don't have to nest promise chains the way you are, and in this case its probably better that you didn't. If you simply return a promise from within a promise callback, you can chain it at the same level, like this:

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;
});

Second, in the error handler you had before you were simply returning the err. This is probably a bad idea because it tells the consumer of your promise that everything is hunky dory and that they should proceed as such. Throwing an error on the other hand will allow that consumer to handle the error however they want in their own .fail block.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM