简体   繁体   English

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

[英]Testing pre-defined callback function with Mocha.js

I am trying to write a test for the following function. 我正在尝试为以下功能编写测试。

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

The test is checking to see if the function returns an object. 该测试正在检查该函数是否返回对象。 resJson is the object being returned and tested. resJson是要返回并测试的对象。

Below is the test case written using Mocha.js and Chai.js assertion library. 下面是使用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);
    });

});

However, when I run the test it fails with the following console output. 但是,当我运行测试时,它失败并显示以下控制台输出。 Saying that resJson is undefined. resJson是不确定的。 I'm guessing that Mocha is trying to assert that resJson is an object BEFORE the function services() returns the object, but I am not sure how to resolve this. 我猜想Mocha试图在函数services()返回对象之前断言resJson是一个对象,但是我不确定如何解决这个问题。

 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)

I have tried to search this online, I have seen people resolve this using done() method. 我尝试过在线搜索,我看到人们使用done()方法解决了这个问题。 However in my case that does not work due to the fact I am using a callback inside my services() function. 但是,由于我在我的services()函数中使用了回调,因此无法正常工作。

I suggest you read this question concerning usage of asynchronous functions 我建议您阅读有关异步函数用法的问题


You can't assign asynchronous function call to variable just as you do in var object = sendRequest.services(api) . 您不能像在var object = sendRequest.services(api)那样将异步函数调用分配给变量。 You need to use callback , which should be added as a parameter to services function 您需要使用callback ,应将它作为参数添加到services函数中

function services(api, callback){
    // your logic here
}

And instead performing return resJson you can call callback(resJson) in the services function. 代替执行return resJson您可以在services函数中调用callback(resJson) Then, in your test, you need to call the services with second parameter being a function(result) 然后,在测试中,您需要使用第二个参数作为function(result)来调用services function(result)

sendRequest.services(api, function(result){
    assert.isObject(result);
});

EDIT 编辑

This is how your services function should look like 这就是您的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);
        }
    }); 
}

Your code looks like it is doing an asynchronous request sendRequest.services(api); 您的代码似乎正在执行异步请求sendRequest.services(api);

What you need to do is handle the done() callback that is made available in the mocha test: it('services() should return an object of services', function(done) {}) 您需要做的是处理在Mocha测试中可用的done()回调: it('services() should return an object of services', function(done) {})

What you need to do is re-write your services function because it is incorrect. 您需要做的是重新编写services功能,因为它不正确。 You cannot return from an asynchronous function, async functions are generally I/O based and do not block the main Nodejs thread. 您不能从异步函数返回,异步函数通常基于I / O,并且不会阻塞Nodejs主线程。 In order for your main thread to access the value you have to pass in a callback function that will be executed once the value is made available. 为了使您的主线程访问该值,您必须传递一个回调函数,该回调函数将在该值可用后执行。

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

And rewrite your test like so: 并这样重写测试:

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

});

I would go even further and pass in the error to the callback function (this is common practice in nodejs): 我将走得更远,并将错误传递给回调函数(这是nodejs中的常见做法):

cb(err, resJson);

And your test can print the error for better debugging: 您的测试可以打印错误以进行更好的调试:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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