承诺和间谍的单元测试

时间:2015-10-14 21:54:36

标签: 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");
                    logger.info("added");
                },
                function (err) {
                    console.log("error");
                    logger.info("error");
                }
            );
        }
    };
};

module.exports = target;

targetTest.js

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方法是异步的,所以还没有执行。是否有适当的模式。

1 个答案:

答案 0 :(得分:2)

这更像是一个关于'Promises如何工作'的问题而不是它们在测试框架中的工作方式 - 答案是它们的行为保持完全相同。

  

是否有正确执行此操作的模式。

这不是一个模式,而是Promise的构建方式。 then的每个成功处理程序在最后一次成功时按顺序执行。在您的代码中,我们可以返回通过调用repository#add创建的Promise,就像您想要使用其结果或在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");
        });
}

然后将您的期望置于then内,该addTarget将在target.addTarget("target").then(function () { expect(mockLogger.info.calledWith("error")).to.be.true; cb(); }); 中创建的Promise链的所有成员成功执行:

cb

异步测试

您将在上面的示例中注意到还有对函数it的调用。由于您的测试是异步的,您需要在测试完成时“告诉”测试框架。这通常是通过使用参数声明describe("target", function () { it("should log error when it occurs", function (cb) { // ^^^^ }); }); 函数来完成的,框架将从该参数推断测试是异步的并传递回调:

String