【问题标题】:How to unit test nested function in node js?如何在节点 js 中对嵌套函数进行单元测试?
【发布时间】:2019-08-22 06:05:10
【问题描述】:

我有一个正在为其编写单元测试的函数,但该函数正在调用另一个函数,因此我无法模拟/存根该函数。

例如:

function getValue( param1, param2, callback){
    getData(param1, param3).then( response) => {
         return callback();
    }, (err) => {
         return callback();
    });
}

所以我不知道如何模拟getData() 函数。

【问题讨论】:

  • getData 定义在哪里?
  • getData 在我正在导入的其他文件中定义。
  • 然后相应地提出问题,如果它是随机函数,则无法模拟getData,只有它是一个导入。
  • 为了完整起见,可以模拟getData,即使它是同一文件中的随机函数,但必须导出 b> 并且必须使用 module export 调用它。 (请参阅this answer 了解 ES6 版本,Node.js 模块将像这样导出 getDataexports.getData = getData;,然后在 getValue 中调用它,像这样:exports.getData(...)
  • 嘿@brian-lives-outdoors getData 正在导出。

标签: node.js mocha.js sinon chai


【解决方案1】:

这是一个演示您正在尝试做什么的工作示例:

lib.js

function getData(param1, param2) {
  return fetch('someUrl');  // <= something that returns a Promise
}

exports.getData = getData;

code.js

const lib = require('./lib');

export function getValue(param1, param2, callback) {
  return lib.getData(param1, param2).then(response => {
    callback(response);
  }).catch(err => {
    callback(err);
  });
}

exports.getValue = getValue;

code.test.js

const sinon = require('sinon');

const lib = require('./lib');
const { getValue } = require('./code');

describe('getValue', () => {
  it('should do something', async () => {
    const stub = sinon.stub(lib, 'getData');
    stub.resolves('mocked response');

    const callback = sinon.spy();
    await getValue('val1', 'val2', callback);

    sinon.assert.calledWithExactly(stub, 'val1', 'val2');  // Success!
    sinon.assert.calledWithExactly(callback, 'mocked response');  // Success!
  });
});

更新

在 cmets 中添加了他们不能使用 async / await 并正在使用 module.exports = getData; 导出函数的 OP。

在这种情况下,模块导出函数,整个模块需要用proxyquire之类的东西来模拟。

断言应该在then回调中完成,测试应该返回结果Promise,所以mocha知道等待它解决。

更新示例:

lib.js

function getData(param1, param2) {
  return fetch('someUrl');  // <= something that returns a Promise
}

module.exports = getData;

code.js

const getData = require('./lib');

function getValue(param1, param2, callback) {
  return getData(param1, param2).then(response => {
    callback(response);
  }).catch(err => {
    callback(err);
  });
}

module.exports = getValue;

code.test.js

const sinon = require('sinon');
const proxyquire = require('proxyquire');

describe('getValue', () => {
  it('should do something', () => {
    const stub = sinon.stub();
    stub.resolves('mocked response');

    const getValue = proxyquire('./code', { './lib': stub });

    const callback = sinon.spy();
    return getValue('val1', 'val2', callback).then(() => {
      sinon.assert.calledWithExactly(stub, 'val1', 'val2');  // Success!
      sinon.assert.calledWithExactly(callback, 'mocked response');  // Success!
    });
  });
});

【讨论】:

  • 嘿,我正在使用module.exports = getData,async() 在节点 js 6 中也不起作用,截至目前它正在抛出以下错误 TypeError: Cannot stub non-existent own property getData。请回复 。谢谢
  • 我添加了一个更新,其中包含一个适用于这些约束的示例。 @ankuselfie
  • TypeError: Cannot read property 'then' of undefined 这是我得到的。实际函数也被调用。
  • 嘿@brian-lives-outdoors 这不起作用,它仍然没有存根“getData”函数。谢谢:)
【解决方案2】:
function getValue( param1, param2, callback){
    getData(param1, param3).then( response) => {
         callback(response);
    });
}

getvalue(param1, param2, function(error, response)) {
   console.log(response)
}

也许对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-24
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 2021-08-02
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多