【问题标题】:Node.js - Mock result of a promiseNode.js - 模拟承诺的结果
【发布时间】:2019-06-01 09:36:57
【问题描述】:

我想在节点模块中模拟一个函数的结果,以便我可以运行断言。 考虑以下节点模块:

const doPostRequest = require('./doPostRequest.js').doPostRequest;
const normalizeSucessResult = require('./normalizer.js').normalizeSucessResult;
const normalizeErrorResult = require('./normalizer.js').normalizeErrorResult;

exports.doPost = (params, postData) => {
  return doPostRequest(params, postData).then((res) => {
    const normalizedSuccessResult = normalizeSucessResult(res);
    return normalizedSuccessResult;
  }).catch((err) => {
    const normalizedErrorResult = normalizeErrorResult(err);
    return normalizedErrorResult;
  })
}

函数doPostRequest 返回一个承诺。我怎样才能伪造这个承诺的返回值,以便我可以断言 normalizeSucessResult 是否已被调用? 所以我试过了:

const normalizeSucessResult = require('./normalizer.js');
const doPostRequest = require('./doPostRequests.js');
const doPost = require('./doPost.js');

it('runs a happy flow scenario', async () => {
  let normalizeSucessResultStub = sinon.stub(normalizeSucessResult, 'normalizeSucessResult');
  let postData = { body: 'Lorum ipsum' };
  let params = { host: 'someUrl', port: 433, method: 'POST', path: '/' };

  sinon.stub(doPostRequest, 'doPostRequest').resolves("some response data"); //Fake response from doPostRequest

  return doPost.doPost(params, postData).then((res) => { //res should be equal to some response data
    expect(normalizeSucessResultStub).to.have.been.calledOnce;
    expect(normalizeSucessResultStub).to.have.been.with("some response data");
  });
});

doPostRequest 模块如下所示:

const https = require('https')
 module.exports.doPostRequest = function (params, postData) {
  return new Promise((resolve, reject) => {
    const req = https.request(params, (res) => {
      let body = []
      res.on('data', (chunk) => {
        body.push(chunk)
      })
      res.on('end', () => {
        try {
          body = JSON.parse(Buffer.concat(body).toString())
        } catch (e) {
          reject(e)
        }
        resolve(body)
      })
    })
    req.on('error', (err) => {
      reject(err)
    })
    if (postData) {
      req.write(JSON.stringify(postData))
    }
    req.end()
  })
}

【问题讨论】:

  • doPostRequest 在哪里定义?请发布所有相关代码。
  • doPostRequest 模块在单独的文件中定义。我已经更新了代码以显示它的位置。如果您对如何解决此问题有任何想法,请分享。我越来越困惑...
  • 我无法提供详细的答案,但是您需要模拟从中导出 doPostRequest 的模块(使用 Proxyquire 或类似的东西),并在导入第一次使用它的模块之前执行此操作(即doPost)模块。你不能用诗乃做到这一点。您只能使用 Sinon 模拟现有方法,而 doPostRequest 用作函数,而不是方法。顺便说一句,Jest 本地处理模块模拟,您可以通过切换到它来更轻松地做到这一点。

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


【解决方案1】:

您可以使用Promise.resolve 返回具有任何给定值的承诺。

Promise.resolve(“hello world”);

【讨论】:

  • 感谢您的帮助,我在我的代码中使用sinon.stub(doPostRequest, 'doPostRequest').resolves("some response data"); 进行了尝试。比我调用该方法时,res 应该等于some response data,但事实并非如此。你能告诉我如何在我的测试中使用它,使res 等于some response data
【解决方案2】:

对于你的函数,你需要这样做

sinon.stub({doPostRequest}, 'doPostRequest').resolves("some response data")

【讨论】:

    【解决方案3】:

    好的,我想通了。函数doPostRequest 使用require 加载,在文件顶部使用const doPostRequest = require('./doPostRequest.js').doPostRequest; 加载

    为了模拟从使用require 加载的函数返回的数据,我必须使用一个名为mock-require 的节点模块。有更多的模块可以解决这个问题(proxyquire 是一个受欢迎的模块)但我选择了 mock-require(我没有选择 mock-require 的具体原因)。

    对于遇到类似问题的其他人,请尝试 mock-require 模拟使用 require 加载的文件的响应。

    【讨论】:

      猜你喜欢
      • 2014-03-23
      • 1970-01-01
      • 2014-09-14
      • 1970-01-01
      • 2017-08-04
      • 2016-09-17
      • 2017-10-18
      • 1970-01-01
      • 2018-08-12
      相关资源
      最近更新 更多