Sinon.stub不是私有方法的存根

时间:2015-07-09 10:09:12

标签: node.js mocha sinon

在下面的模块中,我有一个私有方法,它创建一个临时目录。我正在编写此模块的测试resize,并希望将其私有方法createTmpFile存根并返回虚假目录。我正在使用sinon来执行此操作,但仍在调用原始方法。

我已尝试使用var _private = require('../lib/modules/resizer')._private;的私有方法,然后使用tmpStub = sinon.stub(_private, 'createTmpFile', function () { return "/temporary/"});

在我的测试套件中将其删除

这不会引发任何错误,但仍然会停止调用该函数。

如何用存根替换私有方法?

resize

'use strict';

// dependencies
var gm = require('gm').subClass({ imageMagick: true });
var tmp = require('tmp');
var async = require('async');

var resizer = {};

resizer.resize = function (path, sizesObj, callback) {
    console.log(path);

    var directory = createTmpFile();

    var imgType = path.split(".").pop();

    async.each(sizesObj, function (sizesObj, mapNext) {
        gm(path)
            .resize(sizesObj.width, sizesObj.height)
            .write(directory + sizesObj.name + "." + imgType, function (err) {
                if (err) {
                    mapNext(err);
                }
                mapNext();
            });
    }, function (err) {
        if(err) {
            callback(err);
        } else {
            callback(directory);
        }
    });
};

// This function creates a temporary directory to which we will save our files.
var createTmpFile = function () {

    var tmpDir = tmp.dirSync(); //object
    var tmpDirName = tmpDir.name + "/"; //path to directory
    return tmpDirName;
};

module.exports = resizer;

if ( process.env.NODE_ENV === 'test') {
    module.exports._private = {
        createTmpFile: createTmpFile
    }
};

test

   describe("resizer when data is path", function () {
        var testedModule, dir, sizesObj, tmpStub, writeStub250, writeStub500, writeStub650, writeStub750, callbackSpy, resizeStub, gmSubClassStub;
        var _private = require('../lib/modules/resizer')._private;
        console.log(_private.createTmpFile);

        before(function () {

            dir = "/tmp/rstest.png";

            sizesObj = [
                {name: "thumb", width: 250, height: 250},
                {name: "small", width: 500, height: 500},
                {name: "medium", width: 650, height: 650},
                {name: "large", width: 750, height: 750}
            ];


            writeStub250 = sinon.stub();
            writeStub500 = sinon.stub();
            writeStub650 = sinon.stub();
            writeStub750 = sinon.stub();

            resizeStub = sinon.stub();

            tmpStub = sinon.stub(_private, 'createTmpFile', function () { return "/temporary/"});

            gmSubClassStub = sinon.stub();

            callbackSpy = sinon.spy();

            testedModule = proxyquire('../lib/modules/resizer', {
                'gm': {subClass: sinon.stub().returns(gmSubClassStub)}
            });

        });

        after(function () {
            _private.createTmpFile.restore();
        });

        it("resize image and write to path", function () {

            resizeStub.withArgs(250, 250).returns({write:writeStub250});
            resizeStub.withArgs(500, 500).returns({write:writeStub500});
            resizeStub.withArgs(650, 650).returns({write:writeStub650});
            resizeStub.withArgs(750, 750).returns({write:writeStub750});

            // Stub is used when you just want to simulate a returned value
            gmSubClassStub.withArgs(dir).returns({resize:resizeStub});

            // Act - this calls the tested method
            testedModule.resize(dir, sizesObj, function (err) {
                callbackSpy.apply(null, arguments);
            });

            expect(writeStub250).has.been.called.and.calledWith("/temporary/thumb.png");
        });
});

2 个答案:

答案 0 :(得分:2)

问题在于,您将_private.createTmpFile存根,其中包含引用到您的私人功能。您正在使用存根替换引用,但这与存根原始函数不同。

除非您在调整大小功能中实际使用exports._private.createTmpFile(这不是您想要的,因为exports._private环境中只存在test),否则您将无法使用存根但实际功能(因为createTmpFile仍指向原始功能)。

说实话,不确定是否有一个干净的解决方法。

答案 1 :(得分:0)

感谢@robertklep的评论,我决定再次使用proxyquire解决这个问题,然后找到通过我的测试的以下解决方案。

我已将tmp.dirSync添加到proxyquire并强制它返回假目录,从而更改了设置。我还删除了临时目录的存根。

describe("resizer when data is path", function () {
    var testedModule, dir, sizesObj, writeStub250, writeStub500, writeStub650, writeStub750, callbackSpy, resizeStub, gmSubClassStub;

    before(function () {

        dir = "/tmp/rstest.png";

        sizesObj = [
            {name: "thumb", width: 250, height: 250},
            {name: "small", width: 500, height: 500},
            {name: "medium", width: 650, height: 650},
            {name: "large", width: 750, height: 750}
        ];


        writeStub250 = sinon.stub();
        writeStub500 = sinon.stub();
        writeStub650 = sinon.stub();
        writeStub750 = sinon.stub();

        resizeStub = sinon.stub();

        gmSubClassStub = sinon.stub();

        callbackSpy = sinon.spy();

        testedModule = proxyquire('../lib/modules/resizer', {
            'gm': {subClass: sinon.stub().returns(gmSubClassStub)},
            'tmp': {
                'dirSync': function () {
                    return {
                        name: "/temporary"
                    }
                }
            }
        });
    });

    it("resize image and write to path", function () {

        resizeStub.withArgs(250, 250).returns({write:writeStub250});
        resizeStub.withArgs(500, 500).returns({write:writeStub500});
        resizeStub.withArgs(650, 650).returns({write:writeStub650});
        resizeStub.withArgs(750, 750).returns({write:writeStub750});

        // Stub is used when you just want to simulate a returned value
        gmSubClassStub.withArgs(dir).returns({resize:resizeStub});

        // Act - this calls the tested method
        testedModule.resize(dir, sizesObj, function (err) {
            callbackSpy.apply(null, arguments);
        });

        expect(writeStub250).has.been.called.and.calledWith("/temporary/thumb.png");
        expect(writeStub500).has.been.called.and.calledWith("/temporary/small.png");
        expect(writeStub650).has.been.called.and.calledWith("/temporary/medium.png");
        expect(writeStub750).has.been.called.and.calledWith("/temporary/large.png");

    });

    it("calls callbackSpy", function () {

        writeStub250.callsArgWith(1, null);
        writeStub500.callsArgWith(1, null);
        writeStub650.callsArgWith(1, null);
        writeStub750.callsArgWith(1, null);

        resizeStub.withArgs(250, 250).returns({write:writeStub250});
        resizeStub.withArgs(500, 500).returns({write:writeStub500});
        resizeStub.withArgs(650, 650).returns({write:writeStub650});
        resizeStub.withArgs(750, 750).returns({write:writeStub750});

        // Stub is used when you just want to simulate a returned value
        gmSubClassStub.withArgs(dir).returns({resize:resizeStub});

        // Act - this calls the tested method
        testedModule.resize(dir, sizesObj, function (err) {
            callbackSpy.apply(null, arguments);
        });

        expect(callbackSpy).has.been.called.and.calledWith('/temporary/');
    });
});