使用Mocha.js测试预定义的回调函数

时间:2017-02-17 14:24:50

标签: javascript node.js testing asynchronous mocha

我正在尝试为以下函数编写测试。

function services(api){
    request(`${api}?action=services`, function(err, res, body) {
        if (!err && res.statusCode === 200){
            var resJson = JSON.parse(body);
            var numberOfServices = resJson.length;
            console.log("Service called: services");
            console.log("-----------");
            for (i = 0; i < numberOfServices; i++){
                console.log("Service ID: " + resJson[i].service);
                console.log("Service Name: " + resJson[i].name);
                console.log("-----------");
            }
            return resJson;
        }
    }); 
}

测试是检查函数是否返回一个对象。 resJson是返回和测试的对象。

下面是使用Mocha.js和Chai.js断言库编写的测试用例。

var chai = require('chai');
var assert = chai.assert;
var sendRequest = require('../request');

describe('Test 1', function() {

    var api = 'http://instant-fans.com/api/v2';

    it('services() should return an object of services', function(done) {
        var object = sendRequest.services(api);
        assert.isObject(object);
    });

});

但是,当我运行测试时,它会失败并显示以下控制台输出。说resJson未定义。我猜测Mocha试图在函数resJson返回对象之前断言services()是一个对象,但我不知道如何解决这个问题。

 Test 1
    1) services() should return an object of services

 0 passing (27ms)
 1 failing

  1) Test 1 services() should return an object of services:
     AssertionError: expected undefined to be an object
      at Function.assert.isObject (node_modules/chai/lib/chai/interface/assert.js:555:35)
      at Context.<anonymous> (test/requestTest.js:11:16)

我尝试在线搜索,我看到有人使用done()方法解决此问题。但是在我的情况下由于我在services()函数中使用回调的事实不起作用。

2 个答案:

答案 0 :(得分:0)

我建议你阅读关于异步函数使用的question

您不能像在var object = sendRequest.services(api)中那样为变量分配异步函数调用。您需要使用callback,该services应作为参数添加到function services(api, callback){ // your logic here } 函数

return resJson

而是执行callback(resJson),您可以在services函数中调用services。然后,在测试中,您需要调用function(result),其中第二个参数为sendRequest.services(api, function(result){ assert.isObject(result); });

services

修改

这就是function services(api, callback){ request(`${api}?action=services`, function(err, res, body) { if (!err && res.statusCode === 200){ var resJson = JSON.parse(body); var numberOfServices = resJson.length; console.log("Service called: services"); console.log("-----------"); for (i = 0; i < numberOfServices; i++){ console.log("Service ID: " + resJson[i].service); console.log("Service Name: " + resJson[i].name); console.log("-----------"); } callback(resJson); } }); } 函数的样子

[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target

[Service]
User=mongodb
ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf

[Install]
WantedBy=multi-user.target

答案 1 :(得分:0)

您的代码看起来正在执行异步请求sendRequest.services(api);

您需要做的是处理mocha测试中提供的done()回调:it('services() should return an object of services', function(done) {})

您需要做的是重新编写services函数,因为它不正确。你不能从异步函数返回,异步函数通常是基于I / O的,不要阻塞主Nodejs线程。为了让您的主线程访问该值,您必须在回调函数中传递该函数,该函数将在值可用后执行。

function services(api, cb){
    request(`${api}?action=services`, function(err, res, body) {
        var resJson;
        if (!err && res.statusCode === 200){
            resJson = JSON.parse(body);
            var numberOfServices = resJson.length;
            console.log("Service called: services");
            console.log("-----------");
            for (i = 0; i < numberOfServices; i++){
                console.log("Service ID: " + resJson[i].service);
                console.log("Service Name: " + resJson[i].name);
                console.log("-----------");
            }
        }
        if (cb) {
            cb(err, resJson);
        }
    }); 
}

并像这样重写你的测试:

describe('Test 1', function() {
    var api = 'http://instant-fans.com/api/v2';

    it('services() should return an object of services', function(done) {
        sendRequest.services(api, function(resJson) {
            assert.isObject(resJson);
            done();
        });
    });

});

我会更进一步并将错误传递给回调函数(这是nodejs中的常见做法):

cb(err, resJson);

您的测试可以打印错误以便更好地进行调试:

sendRequest.services(api, function(err, resJson) {
    if (err) {
        console.error(err);
    }
    assert.isObject(resJson);
    done();
});