如何在节点 js 中对嵌套函数进行单元测试?

Posted

技术标签:

【中文标题】如何在节点 js 中对嵌套函数进行单元测试?【英文标题】:How to unit test nested function in node 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 正在导出。 【参考方案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)

也许对你有帮助。

【讨论】:

以上是关于如何在节点 js 中对嵌套函数进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

函数——基本语法,嵌套匿名高阶递归函数

如何在 vis.js 时间轴中对嵌套组进行排序?

如何在Node.js中对使用promises和事件发射器的函数进行单元测试?

如何对 Vue 应用程序中的嵌套操作进行单元测试?

如何在javascript中对嵌套的对象数组进行排序?

我们如何为嵌套函数编写单元测试用例(Jasmine)?