javascript - 在测试使用 Promise 的 Node 模块时如何断言?

标签 javascript node.js mocha.js q sinon

我有一个 Node Controller “simpleController”,它依赖于“DataAccess”的实例。 Controller 在“DataAccess”实例上调用函数“getData”,并返回一个 promise 。如果 promise 随后被拒绝, Controller 应返回状态 500。

我想在“simpleController”上编写一个测试,但模拟“DataAccess”的实例,以便我可以返回失败的 promise 并断言“simpleController”行为符合预期。

我尝试编写一个单元测试来执行此操作,但测试超时。

(function (simpleController) {

    var DataAccess = require('./DataAccess');

    var dataAccessInstance;

    simpleController.init = function (dataSource) {
        dataAccessInstance = new DataAccess(dataSource);
    };

    simpleController.setMockDependencies = function (mockDataAccessInstance) {
        dataAccessInstance = mockDataAccessInstance;
    };

    simpleController.performAction = function (req, res) {

        var entityId = req.query.id;

        dataAccessInstance.getData(entityId)
            .then(function (data){
                res.status(200).json(data);
            },
            function (err) {
                res.status(200).json(err);
            });
    }

})(module.exports);



/* global describe, it */
'use strict';

var assert = require('assert');
var sinon = require('sinon');
var Q = require('q');
var DataAccess = require('../lib/temp/DataAccess');

describe('Simple Controller Tests', function () {

    var simpleController;
    var dataAccess;

    beforeEach(function (done) {

        simpleController = require('../lib/temp/simpleController');

        var dataSource = 'dummy';
        dataAccess = new DataAccess(dataSource);

        done();
    });


    it('should return status of 500 if data access fails', function (done) {

        // Arrange
        var req = { query: { id: '12345678' } };
        var res = {};

        var deferred = Q.defer();

        var stub = sinon.stub(dataAccess, 'getData', function() {
            return deferred.promise;
        });

        simpleController.setMockDependencies(dataAccess);

        deferred.promise.fail(function () {

            // Assert
            assert.ok(stub.called);
            assert.equal(res.status, 500);

            done();

        });

        // Act
        simpleController.performAction(req, res);

        deferred.reject();
    });

});



(function () {

    function DataAccess(dataSource) {
        this.dataSource = dataSource;
    }

    DataAccess.prototype.getData = function (entityId) {
        throw new Error('Not implemented');
    };

    module.exports = DataAccess;
})();

任何帮助将不胜感激。

最佳答案

据我所知,您遇到的问题是您在两个地方为您的 promise 提供了失败处理程序。一次是在测试中调用 deferred.promise.fail ,一次是在 Controller 中将第二个参数传递给 dataAccessInstance.getData(entityId).then 。您的 Controller 中的 Controller 可能会替换您在测试中添加的 Controller 。我建议删除此代码(它实际上没有做任何有用的事情):

deferred.promise.fail(function () {

        // Assert
        assert.ok(stub.called);
        assert.equal(res.status, 500);

        done();

    });

不要在测试中使用空对象作为 res,而是添加一个状态方法,并在那里进行断言:

it('should return status of 500 if data access fails', function (done) {

    // Arrange
    var req = { query: { id: '12345678' } };
    var res = {};

    var deferred = Q.defer();

    var stub = sinon.stub(dataAccess, 'getData', function() {
        return deferred.promise;
    });

    simpleController.setMockDependencies(dataAccess);

    res.status = function (status) {

        // Assert
        assert.ok(stub.called);
        assert.equal(status, 500);

        done();

    };

    // Act
    simpleController.performAction(req, res);

    deferred.reject();
});

另外,请注意,在您的 Controller 中,您使用 200 表示成功和失败,我认为您打算使用 500 表示失败。最后,您应该在 promise 链的末尾添加 .done() :

dataAccessInstance.getData(entityId)
       .then(function (data){
           res.status(200).json(data);
       },
       function (err) {
           res.status(500).json(err);
       })
       .done();

(参见 http://documentup.com/kriskowal/q/#tutorial/the-end )。这将避免测试失败时超时。

关于javascript - 在测试使用 Promise 的 Node 模块时如何断言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28219880/

相关文章:

javascript - $state.reload() 后无法与页面交互

javascript - 如何创建一个自动将内容自动换行的 div,以便 div 永远不会水平增长大于其容器?

javascript - Blazor fire onchange event when Chosen drop down value changes

node.js - 无法在 Heroku 上启动浏览器进程

node.js - sinon 期望的不同参数/返回值

javascript - 通过正则表达式拆分字符串

mysql - Node Js Sequelize 原始查询以 Sequelize ORM

node.js - NodeJs : binary fs. createReadStream 流式传输为 UTF-8

javascript - 如何解决 'Assertions require every name in the call target to be declared with an explicit type annotation.ts(2775)' ?

node.js - Chai 与 should.js 与 Mocha for Node.js