Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 带有承诺和间谍的单元测试_Javascript_Node.js_Unit Testing_Promise_Sinon - Fatal编程技术网

Javascript 带有承诺和间谍的单元测试

Javascript 带有承诺和间谍的单元测试,javascript,node.js,unit-testing,promise,sinon,Javascript,Node.js,Unit Testing,Promise,Sinon,我有以下文件:- target.js var target = function(repository, logger) { return { addTarget : function(target) { repository.add(target).then( function (newTarget) { console.log("added");

我有以下文件:-

target.js

var target = function(repository, logger) {

    return {
        addTarget : function(target) {
            repository.add(target).then(
                function (newTarget) {
                    console.log("added");
                    logger.info("added");
                },
                function (err) {
                    console.log("error");
                    logger.info("error");
                }
            );
        }
    };
};

module.exports = target;
var chai = require("chai"),
    expect = chai.expect,
    sinon = require("sinon"),
    Promise = require("bluebird"),
    baseTarget = require("../target");

describe("target", function(){
    it("should log error when it occurs", function() {
        var mockRepository = {
            add : sinon.stub().returns(Promise.reject(new Error()))
        };

        var mockLogger = {
            info : sinon.spy()
        };

        var target = baseTarget(mockRepository, mockLogger);

        target.addTarget("target");

        expect(mockLogger.info.calledWith("error")).to.be.true;
    });
});
targetTest.js

var target = function(repository, logger) {

    return {
        addTarget : function(target) {
            repository.add(target).then(
                function (newTarget) {
                    console.log("added");
                    logger.info("added");
                },
                function (err) {
                    console.log("error");
                    logger.info("error");
                }
            );
        }
    };
};

module.exports = target;
var chai = require("chai"),
    expect = chai.expect,
    sinon = require("sinon"),
    Promise = require("bluebird"),
    baseTarget = require("../target");

describe("target", function(){
    it("should log error when it occurs", function() {
        var mockRepository = {
            add : sinon.stub().returns(Promise.reject(new Error()))
        };

        var mockLogger = {
            info : sinon.spy()
        };

        var target = baseTarget(mockRepository, mockLogger);

        target.addTarget("target");

        expect(mockLogger.info.calledWith("error")).to.be.true;
    });
});

我遇到的问题是
expect(mockLogger.info.calledWith(“error”)).to.be.true
返回
false
,因为存储库上的
add
方法是异步的,所以尚未执行。是否有一种模式可以正确地做到这一点。

这实际上更多的是一个关于“承诺如何工作”的问题,而不是它们在测试框架中如何工作的问题——答案是它们的行为保持完全相同

是否有一种模式可以正确地执行此操作

这与其说是一种模式,不如说是承诺的目的。
的每个成功处理程序在最后一个成功时按顺序执行。在您的代码中,我们可以返回通过调用
存储库#add
创建的承诺,就像您希望使用其结果或在
addTarget
之外执行一些外部相关操作一样:

addTarget: function (target) {
    return repository
//  ^^^^^^
        .add(target)
        .then(function (newTarget) {
            console.log("added");
            logger.info("added");
        }, function (err) {
            console.log("error");
            logger.info("error");
        });
}
target.addTarget("target").then(function () {
    expect(mockLogger.info.calledWith("error")).to.be.true;
    cb();
});
然后将您的期望放在
中,然后在
addTarget
中创建的承诺链的所有成员成功后执行该

addTarget: function (target) {
    return repository
//  ^^^^^^
        .add(target)
        .then(function (newTarget) {
            console.log("added");
            logger.info("added");
        }, function (err) {
            console.log("error");
            logger.info("error");
        });
}
target.addTarget("target").then(function () {
    expect(mockLogger.info.calledWith("error")).to.be.true;
    cb();
});
异步测试

var target = function(repository, logger) {

    return {
        addTarget : function(target) {
            repository.add(target).then(
                function (newTarget) {
                    console.log("added");
                    logger.info("added");
                },
                function (err) {
                    console.log("error");
                    logger.info("error");
                }
            );
        }
    };
};

module.exports = target;
var chai = require("chai"),
    expect = chai.expect,
    sinon = require("sinon"),
    Promise = require("bluebird"),
    baseTarget = require("../target");

describe("target", function(){
    it("should log error when it occurs", function() {
        var mockRepository = {
            add : sinon.stub().returns(Promise.reject(new Error()))
        };

        var mockLogger = {
            info : sinon.spy()
        };

        var target = baseTarget(mockRepository, mockLogger);

        target.addTarget("target");

        expect(mockLogger.info.calledWith("error")).to.be.true;
    });
});
在上面的示例中,您会注意到还有一个对函数
cb
的调用。由于您的测试是异步的,您需要在测试完成时“告诉”测试框架。这通常是通过使用参数声明
it
函数来实现的,框架将根据该参数推断测试是异步的,并传入回调:

describe("target", function () {
    it("should log error when it occurs", function (cb) {
                                                // ^^^^
    });
});