如何在有承诺的测试工厂中使用间谍?
How to use spies in testing factories with promises?
我想测试这段代码:
'use strict';
var Promise = require('bluebird');
var AWS = require('aws-sdk');
var fs = Promise.promisifyAll(require('fs-extra'));
var path = require('path');
var dispatcher = function() {
return {
/**
* @param {Object} options
* @param {string} options.s3_access_key
* @param {string} options.s3_secret_key
* @param {string} options.s3_bucket
* @param {string} options.file - Path to the file to be uploaded
* @param {string} [options.file_key] - Name to save the file under, defaults to the original file's name
* @returns {Function} Promise - A promise resolved with `true` or rejected with an Error
*/
upload: Promise.method(function upload(options) {
var s3_options = {
accessKeyId: options.s3_access_key,
secretAccessKey: options.s3_secret_key,
params: {
Bucket: options.s3_bucket
}
};
var file_stream = fs.createReadStream(options.file);
var file_key = options.file_key || path.basename(options.file);
var promisedS3 = Promise.promisifyAll(new AWS.S3(s3_options));
return promisedS3.putObjectAsync({
Body: file_stream,
Key: file_key
});
})
};
};
module.exports = {
create: dispatcher
};
我知道如何进行集成测试,但我还想验证是否使用正确的参数调用了 promisedS3
。我想我需要为此使用间谍,但我不确定如何从测试中 "plug" 自己进入 promisedS3.putObjectAsync 以截取参数并进行比较。
我想避免在私有方法中包装对 S3 的调用并继续使用工厂。
(评论后编辑)
在您的测试中,您可以使用 proxyquire 到 stub/mock 外部依赖项之类的库。
我刚刚对此进行了测试并且有效:
'use strict';
var sinon = require( 'sinon' );
var proxyquire = require( 'proxyquire' );
var expect = require('must');
var awsStub = {
S3: function(){
},
'@noCallThru': true
};
var fsStub = {
createReadStream: function(){
return {};
},
'@noCallThru': true
};
describe( 'S3 uploader', function(){
var subject, spy;
beforeEach( function(){
spy = sinon.spy();
awsStub.S3.prototype.putObject = function( params, callback ){
spy(params);
callback();
};
subject = proxyquire( '../lib/s3uploader', {
'aws-sdk': awsStub,
'fs-extra': fsStub
} );
} );
it( 'should delegate to AWS S3 `putObject`', function( done ){
subject().upload( {file:''} ).then( function(){
expect( spy.callCount ).to.equal( 1 );
done();
} )
} );
} );
其中 lib/s3uploader
是您在上面发布的文件。
默认情况下仍然会调用存根依赖的原始方法。如果你不想,你需要将 @noCallThru: true
传递给 proxyquire 调用,如上所述。
我想测试这段代码:
'use strict';
var Promise = require('bluebird');
var AWS = require('aws-sdk');
var fs = Promise.promisifyAll(require('fs-extra'));
var path = require('path');
var dispatcher = function() {
return {
/**
* @param {Object} options
* @param {string} options.s3_access_key
* @param {string} options.s3_secret_key
* @param {string} options.s3_bucket
* @param {string} options.file - Path to the file to be uploaded
* @param {string} [options.file_key] - Name to save the file under, defaults to the original file's name
* @returns {Function} Promise - A promise resolved with `true` or rejected with an Error
*/
upload: Promise.method(function upload(options) {
var s3_options = {
accessKeyId: options.s3_access_key,
secretAccessKey: options.s3_secret_key,
params: {
Bucket: options.s3_bucket
}
};
var file_stream = fs.createReadStream(options.file);
var file_key = options.file_key || path.basename(options.file);
var promisedS3 = Promise.promisifyAll(new AWS.S3(s3_options));
return promisedS3.putObjectAsync({
Body: file_stream,
Key: file_key
});
})
};
};
module.exports = {
create: dispatcher
};
我知道如何进行集成测试,但我还想验证是否使用正确的参数调用了 promisedS3
。我想我需要为此使用间谍,但我不确定如何从测试中 "plug" 自己进入 promisedS3.putObjectAsync 以截取参数并进行比较。
我想避免在私有方法中包装对 S3 的调用并继续使用工厂。
(评论后编辑)
在您的测试中,您可以使用 proxyquire 到 stub/mock 外部依赖项之类的库。
我刚刚对此进行了测试并且有效:
'use strict';
var sinon = require( 'sinon' );
var proxyquire = require( 'proxyquire' );
var expect = require('must');
var awsStub = {
S3: function(){
},
'@noCallThru': true
};
var fsStub = {
createReadStream: function(){
return {};
},
'@noCallThru': true
};
describe( 'S3 uploader', function(){
var subject, spy;
beforeEach( function(){
spy = sinon.spy();
awsStub.S3.prototype.putObject = function( params, callback ){
spy(params);
callback();
};
subject = proxyquire( '../lib/s3uploader', {
'aws-sdk': awsStub,
'fs-extra': fsStub
} );
} );
it( 'should delegate to AWS S3 `putObject`', function( done ){
subject().upload( {file:''} ).then( function(){
expect( spy.callCount ).to.equal( 1 );
done();
} )
} );
} );
其中 lib/s3uploader
是您在上面发布的文件。
默认情况下仍然会调用存根依赖的原始方法。如果你不想,你需要将 @noCallThru: true
传递给 proxyquire 调用,如上所述。