在下面的模块中,我有一个私有方法,它创建一个临时目录。我正在编写此模块的测试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");
});
});
答案 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/');
});
});