如何存根request.get三次?有2个相同的网址和1个不同的网址?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何存根request.get三次?有2个相同的网址和1个不同的网址?相关的知识,希望对你有一定的参考价值。

我需要为下面的代码编写单元测试用例。这里的url是外部api调用,所以我需要嘲笑这些。对于其他测试用例,我使用过sinon。所以想在sinon中写这些。

function 1 {
  async.waterfall() {
    function 2();
    function 3();
  }
}

function 2(callback) {
    url2_1 = "/calculatorFunctionList"
    request.get(url2_1,function (err, res, body) {
        return callback("with some diff response")
    })}

function 3(callback) {
    url3_1 = "addition/values="+somevalue1
    url3_2 = "addition/values="+somevalue2
    request.get(url3_1,function (err, res, body) {
        if(!err) {
            request.get(url3_2, function (err, res, body) {
                return callback("with some response")
            })
        }
    })
}

我需要存根这些请求。我怎样才能做到这一点?如何以及何时调用存根的恢复以便它不会搞乱其他请求存根?目前这两个存根都没有被嘲笑。

答案

Sinon - 其核心(暂时忘记lolexnise) - 明确处理对javascript函数的存根和间谍。而已。它本身并不涉及模块加载器或节点本身。

所以它不知道如何挂钩到Node的模块加载器(require)并自己删除依赖关系。对于一般情况,您有两种选择:

  1. 为您的模块(系统测试中)提供注入点(例如,function setRequestModule(module){ request = module },可用于提供Sinon存根。
  2. 使用链接级别拦截对模块系统的调用以加载依赖项并将其交换出来。有关如何执行此操作,请参阅this article on Sinon's how-to section

这是一般情况,但由于您正在处理网络级别存根,因此有第三个选项与第二个选项相关,其中涉及挂接到Node中的http层并使用nock设置虚假请求和响应。

这看起来像这样:

const nock = require('nock')

const scope = nock('https://api.github.com')
  .get('/repos/atom/atom/license')
  .reply(200, {
    license: {
      key: 'mit',
      name: 'MIT License',
      spdx_id: 'MIT',
      url: 'https://api.github.com/licenses/mit',
      node_id: 'MDc6TGljZW5zZTEz',
    },
  })

这就是我通常会做的,但由于你坚持只使用Sinon,你可以选择第一个选项。

第一个选项的详细说明:注入依赖项

您的函数23(无效的javascript标识符,顺便说一句)都依赖于模块request及其方法get来获得结果。为了能够控制request.get返回的内容,您需要为您的模块提供不同版本的request以供测试。这可以使用依赖注入来完成。

首先,我假设你的函数以导入request模块开始,这意味着前几行包含一个如下所示的语句:

const request = require('request');

您需要更改此语句,以便可以替换request常量,这意味着它现在看起来像这样:

let request = require('request');

为了能够控制您的依赖关系,您现在可以为导出添加一个新函数:

module.exports.setRequestModule = function (stub){
    request = stub;
}

要在测试中使用它,您需要在测试中执行此操作:

const myModule = require('../src/my-module');
const myRequestStub = {};

myModule.setRequestModule(myRequestStub);

it('should return the expected response', () => {
    const expectedOutput = "with some response";
    myRequestStub.get = function (url, callback) {
         callback(null, expectedOutput);
    }

    myModule.doSomething() ...
    // do test
});

或者您也可以在模块中公开请求对象:

module.exports._request = request;

例如,您可以使用sinon通过从测试中删除get方法来对其进行检测。

const myModule = require('../src/my-module');

sinon.stub(myModule._request, 'get').callsFake( (url, cb) => cb("hello!") );

以上是关于如何存根request.get三次?有2个相同的网址和1个不同的网址?的主要内容,如果未能解决你的问题,请参考以下文章

检查是否调用了一个stubbed方法三次

如何告诉 Pex 不要存根具有具体实现的抽象类

数据分析师如何构建自己的网气 IP

有没有办法用 Rspec 存根包含模块的方法?

wireshark抓包直观图解 TCP三次握手/四次挥手详解

十二银元分三次找一假