如何使用sinon.js框架对https.request的response.pipe进行桩测试?

5
假设我有这段简单的代码:
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有点新,想问一下:如何stub response.pipe()? 当然,我可以为https.request创建一个stub,并使用.on和.end返回一些内容,这很容易,但我不知道如何测试response.pipe()是否以正确的参数调用...(Node.js文档说response是回调函数) 在这种情况下,文档没有帮助! 当然,测试环境是mocha,并且还可以使用chai,请给我一些建议或示例。 谢谢,Matt

2个回答

6

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

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。或者将所有这些准备工作提取到一个单独的方法中,并在测试中只保留断言。


3

从Sinon文档中可以看到,这个功能已从v3.0.0版本中移除:

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

相反,你应该使用:

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

2
嘿,给你个金铲子,伙计 :) 希望这个能用。 - Arogancky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接