如何在节点 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 模块将像这样导出 getData
:exports.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 中对嵌套函数进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章