2015-10-11 43 views
0

我想測試此代碼:如何在承諾測試工廠中使用間諜?

'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被調用用正確的參數。我想我需要使用間諜,但我不知道如何將自己「插入」測試中的promisedS3.putObjectAsync以攔截參數並進行比較。

我想避免用私有方法打包調用S3並繼續使用工廠。

+0

你看過使用sinon嗎? –

+0

我有,但我不知道我完全理解如何從我的代碼中進入'promisedS3'對象。我可以'var spy = sinon.spy(require('./ dispatcher'),'upload');'但我不明白它是如何幫助我窺探'promisedS3.putObjectAsync'調用。 – springloaded

+0

請在對象的原型而不是每個新實例上調用'promisifyAll',這會顯着加快。 –

回答

1

(評論後可進行編輯)

在你的測試,你可以使用庫像proxyquire存根/模擬外部依賴。

我只是測試了這一點,它的工作原理:

'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調用,如上所述。

+0

'Promise.promisfyAll(new AWS.S3());'使這不起作用。我認爲,我無法訪問'promisedS3',因爲它不在模塊的全局範圍內。如果我嘲笑'AWS.S3.putObject',當我檢查'upload'內的'AWS.S3'對象時,我可以看到模擬,但是當我使用'new AWS.S3()'然後promisify它時, 'putObject'方法不是模擬。 – springloaded

+0

啊,是的,我沒有意識到這是一個「班級」。正如本傑明格魯恩鮑姆寫道,你必須提出原型,而不是實例。我會更新我的答案。 – Creynders

+0

用經過驗證的代碼更新了我的答案。 – Creynders