【问题标题】:How to mock request module with rewire?如何使用 rewire 模拟请求模块?
【发布时间】:2016-11-27 05:15:58
【问题描述】:

我有一个自定义模块 tokens.js,它具有通过 npm 请求模块 发出请求的功能。它看起来像这样:

'use strict';

let request = require('request');

module.exports.getToken = function(code, cb) {
  let url = 'some_url';

  request(url, function (err, response, body) {
    if (err) {
      return cb(err);
    } else if (response.statusCode !== 200) {
      return cb('err');
    }

    parseGetResponse(body, function (err, token) {
      if (err) {
        return cb(err);
      }

      return cb(null, token);
  });
});

我想编写单元测试来覆盖getToken()函数,但是我在模拟请求模块时遇到了一些麻烦。

我试过这个:

let mocha = require('mocha');
let rewire = require('rewire');
let should = require('should');

let requestMock = {
  request: function (url, cb) {
      // return cb(); etc
  }
}

let tokens = rewire('services/tokens.js');
tokens.__set__('request', requestMock);

但是这种方法行不通:

TypeError: request is not a function
  at Object.module.exports.getToken (services/tokens.js)

其实,这又引出了另一个问题: 如果不直接调用导出函数(request.request(url, cb)),请求模块如何工作?我应该如何使用 rewire?

【问题讨论】:

    标签: node.js unit-testing request mocking


    【解决方案1】:

    另一种选择是重构代码,以便轻松配置其依赖项。

    function TokenGetter(request) {
       this.request = request || require('request');
       this.getToken = function(code, cb) { ...
    }
    module.exports.TokenGetter = TokenGetter;
    
    // production code
    var tokenGetter = new TokenGetter();
    

    测试代码

    // test code can configure a mock request for your test, no 
    // 3rd party libraries
    // configure mockObject with assertions/return values
    var mockRequest = function(url, cb) { .... ;
    
    var testTokenGetter = new TokenGetter(mockRequest);
    

    有许多策略可以使您的类可配置,并允许注入假对象进行测试。我相信努力编写可测试性代码应该消除向您的项目添加更多第三方依赖项的需要。

    【讨论】:

    • 我什至没有考虑 node.js 中的 DI 方法。我试试这个方法,谢谢。
    • 你能检查stackoverflow.com/questions/46952843/… 我想模拟meteor/meteor 位置,或者一般来说import Meteor from 'meteor/meteor' 不存在,因为我直接使用npm run mocha-tests 开始我的测试而不是meteor test。不幸的是,很多代码都依赖于Meteor 环境。
    【解决方案2】:

    实际上,我找到了一种模拟请求模块的方法。我只是让 requestMock 成为一个函数。我还发现在请求模块中有一行,这使得它成为可能: module.exports = 请求

    【讨论】:

      猜你喜欢
      • 2019-11-14
      • 2019-06-22
      • 1970-01-01
      • 2018-02-24
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 1970-01-01
      相关资源
      最近更新 更多