【问题标题】:How to stub https.request response.pipe with sinon.js?如何使用 sinon.js 存根 https.request response.pipe?
【发布时间】:2017-07-12 23:56:21
【问题描述】:

假设我有这个简单的代码:

var https = require('https');
var options = {
  host: 'openshift.redhat.com',
  port: 443,
  path: '/broker/rest/api',
  method: 'GET'
};
var req = https.request(options, function(response) {
  console.log(response.statusCode);
  response.pipe(save stream to file with fs)
});
req.on('error', function(e) {
  console.error(e);
});
req.end();

好吧,我对 sinon.js 有点陌生,我想问一下:如何存根 response.pipe()? 当然,我可以为 https.request 制作存根并使用 .on 和 .end 返回一些东西,这很容易,但我不知道如何测试 response.pipe() 是否被正确的参数调用......(nodejs文档说响应是回调) 在这种情况下,文档没有帮助! ofc 测试环境是 mocha,也可以使用 chai 请给我一些建议或例子。 谢谢,马特

【问题讨论】:

    标签: javascript node.js unit-testing httprequest sinon


    【解决方案1】:

    我将您的代码包装到一个接受回调的函数中,因为在当前的实现中,我们实际上并不知道管道何时真正完成。所以假设我们有这样的函数:

    const downloadToFile = function (options, callback) {
    	let req = https.request(options, function (err, stream) {
    		let writeStream = fs.createWriteStream('./output.json');
    		stream.pipe(writeStream);
    
    		//Notify that the content was successfully writtent into a file
    		stream.on('end', () => callback(null));
    		//Notify the caller that error happened.
    		stream.on('error', err => callback(err));
    	});
    
    	req.end();
    };

    有3个问题需要解决:

    1. 因为响应是可读流。我们想模拟它发出的数据。
    2. 我们想模拟 .pipe 方法检查我们是否正在管道到正确的流。
    3. 我们还需要模拟 https.request 方法不进行实际调用

    以下是我们如何做到这一点:

    const {PassThrough} = require('stream');
    
    describe('#downloadToFile', () => {
    	it('should save the data to output.json', function (callback) {
    		const mockResponse = `{"data": 123}`;
    		//Using a built-in PassThrough stream to emit needed data.
    		const mockStream = new PassThrough();
    		mockStream.push(mockResponse);
    		mockStream.end(); //Mark that we pushed all the data.
    
    		//Patch the 'https' module not to make an actual call
    		//but to return our stream instead
    		sinon.stub(https, 'request', function (options, callback) {
    			callback(null, mockStream);
    
    			return {end: sinon.stub()}; //Stub end method btw
    		});
    
    		//Finally keep track of how 'pipe' is going to be called
    		sinon.spy(mockStream, 'pipe');
    
    		downloadToFile({url: 'http://google.com'}, (err) => {
    			//Here you have the full control over what's happened
    			sinon.assert.calledOnce(mockStream.pipe);
    			//We can get the stream that we piped to.
    			let writable = mockStream.pipe.getCall(0).args[0];
    			assert.equal(writable.path, './output.json');
    
    			//Tell mocha that the test is finished. Pass an error if any.
    			callback(err);
    		});
    	});
    });

    稍后您可以创建单独的函数,例如:createMockedStream。或者甚至将所有这些准备工作提取到一个单独的方法中,并且只在测试中保留断言。

    【讨论】:

      【解决方案2】:

      从 Sinon 文档中,这已从 v3.0.0 中删除:

      var stub = sinon.stub(object, "method", func);`
      

      你应该使用:

      stub(obj, 'meth').callsFake(fn)
      

      【讨论】:

      • 嘿,金铲子给你伙计 :) 我希望这行得通
      猜你喜欢
      • 2021-02-21
      • 2018-03-06
      • 2016-12-02
      • 2012-01-09
      • 2020-07-01
      • 2016-08-16
      • 1970-01-01
      • 2014-01-31
      • 2012-05-22
      相关资源
      最近更新 更多