簡體   English   中英

Supertest,Mocha和Sinon的單元測試超時

[英]Unit testing with Supertest, Mocha & Sinon timing out

我試圖編寫一個單元/集成測試,我想在其中獲取數據庫中的所有內容。 因為它不僅是一個GET,而且這些測試需要擴展到POST,PUT和DELETE。

到目前為止,我擁有的代碼運行良好,實際上我可以從數據庫中獲取數據,但是一旦我嘗試將負責對數據庫進行調用的函數存根,Mocha就會超時

1個失敗

1)/ account_types GET 200列表:錯誤:超時超過2000ms。 確保此測試中調用了done()回調。 為空。 (C:\\ Code \\ JS \\ general_admin_service \\ node_modules \\ mocha \\ lib \\ runnable.js:215:19)

我知道由於代碼卡在某處而未調用done()回調,但是我不明白自己在做什么錯。

我使用以下參考資料來了解自己的位置:

我的代碼如下:

考試:

'use strict';

var expect = require('chai').expect,
    request = require('supertest'),
    chance = require('chance').Chance(),
    server = require('../server'),
    sinon = require('sinon'),
    select = require('../../helpers/data_access/select');

describe("/account_types", function () {

    before(function(done){
        sinon
            .stub(select, "query_list")
            .returns([{id: "test"}]);

        done();
    });

    after(function(done){
        select
            .query_list
            .restore();

        done();
    });

    it('GET 200 List', function (done) {

        request(server.baseURL)
            .get('/api/v1/account_types')
            .set('Accept', 'application/json')
            .expect('Content-Type', 'application/json')
            .expect(200)
            .end(function (err, res) {
                /* istanbul ignore if */
                if (err)
                    return done(err);

                expect(res.body).to.include.keys('result');
                expect(res.body.result).to.not.be.null;
                expect(res.body.result).to.not.be.undefined;
                expect(res.body.result).to.be.an('Array');
                expect(res.body.result.length).to.be.above(0);

                //expect(select.query_list).to.have.been.calledOnce;

                return done();
            });
    });

});

重新調整端點:

var select = require('../helpers/data_access/select')

module.exports = function (server) {
        var query = "..."

        return select.query_list(res, next, db_config, query);
    });
};

select.js:

var sql = require('mssql');

module.exports = {
    query_list: function (res, next, config, sql_query) {
        return query(res, next, config, sql_query, true);
    },
    query_single: function (res, next, config, sql_query) {
        return query(res, next, config, sql_query, false);
    }
};

function query(res, next, config, sql_query, isList) {
    var connection = new sql.Connection(config);

    connection.connect(function (err) {
        if (err) {
            return on_error(err, res);
        }

        var request = new sql.Request(connection);

        request.query(sql_query, function (err, response) {
            connection.close();

            if (err) {
                return on_error(err, res);
            }

            if (isList) {
                return return_list(res, response, next);
            } else {
                return return_single(res, response, next);
            }
        });
    });
}

function on_error(error, res, next) {
    res.status(500).send(error);
    return next();
}

function return_list(res, response, next) {
    res.send({result: response});
    return next();
}

function return_single(res, response, next) {
    res.send({result: response[0]});
    return next();
}

我期望發生的事情是,因為我不加入query_list函數,所以我應該輸入console.log(res.body.result); 在期望值到位之后,我應該看到[{id: "test"}] ,但是顯然還沒有到此為止。

我究竟做錯了什么?

更新:添加了完整的select.js文件。

正如您已經在注釋中明確指出的那樣,很難測試深度嵌套的代碼。

通常,使用回調或Promise更好,這樣應用程序的每一部分都可以處理它負責的部分,但不能(更多)處理。 因此,您的路由處理程序將處理請求響應。 顯然可以調用其他函數,例如執行數據庫查詢的函數,但是與其讓這些函數發送回響應,不如使用回調將查詢結果“回調”到路由處理程序。

像這樣:

server.get('/api/v1/account_types', function(req, res, next) {
  select.query_list(QUERY, function(err, records) {
    if (err) return next(err);
    res.send({ results : records });
    next();
  });
});

在使用Sinon測試類似的東西方面:它實際上取決於確切的實現。 我可以提供一個簡單的示例,說明如何對select.query_list的上述用法進行select.query_list ,以確保響應包含正確的數據。

基本存根如下所示:

sinon.stub(select, 'query_list').yieldsAsync(null, [ { id : 'test' } ]);

這樣做是在select.query_list()被調用時,它將調用接收到的第一個回調參數(通過檢查每個參數以查看哪個是函數來實現),其參數為null, [ { id : 'test' } ]

這些是errrecords在處理程序中傳遞的回調函數的參數。 因此,您可以使用它完全跳過數據庫查詢,並假裝該查詢產生了特定的記錄數組。

從那里開始,調用res.send() (這是您最初遇到的問題:根本沒有被調用,因為它是在應用程序的一部分中執行的,而由於存根而沒有被調用) ),然后您可以檢查測試結果是否符合預期。

如果您想在調用堆棧中更深地存根某個函數,會變得有些復雜,但是使用正確的Sinon工具(例如.yields*或使用間諜代替存根),通常並不困難(只要所有函數您想存根/間諜是可訪問的(即已導出)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM