为了账号安全,请及时绑定邮箱和手机立即绑定

用 Sinon 存根单个导出函数

用 Sinon 存根单个导出函数

郎朗坤 2021-06-29 07:37:52
我刚刚将我的 lodash 导入从 更改import _ from 'lodash';为import debounce from 'lodash/debounce';在我的测试中我曾经有过sandbox.stub(_, 'debounce').returnsArg(0);,但现在我不知道将其更改为什么。显然sandbox.stub(debounce).returnsArg(0);行不通。当模块中只导出一个函数时,不确定该怎么做。
查看完整描述

2 回答

?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

此语法:


import something from 'myModule';

...是结合ES6语法something的default出口'myModule”。


如果模块是 ES6 模块,那么您可以default像这样存根模块的导出:


import * as myModule from 'myModule';

const sinon = require('sinon');


// ...


const stub = sinon.stub(myModule, 'default');

...但这仅适用'myModule'于 ES6 模块。


在这种情况下'lodash/debounce'不是 ES6 模块,它是预编译的。最后一行是这样的:


module.exports = debounce;

...这意味着模块导出是去抖动功能。


这意味着为了存根,'lodash/debounce'您必须模拟整个模块。


Sinon 不提供模块级模拟,因此您需要使用以下内容proxyquire:


const proxyquire = require('proxyquire');

const sinon = require('sinon');


const debounceStub = sinon.stub().returnsArg(0);

const code = proxyquire('[path to your code]', { 'lodash/debounce': debounceStub })

...或者如果您正在使用,Jest您可以使用以下内容jest.mock:


jest.mock('lodash/debounce', () =>

  jest.fn((func, ms) => func)  // <= mock debounce to simply return the function

);

细节


default仅当模块是 ES6 模块时存根模块的导出才有效的原因是编译期间发生的事情。


ES6 语法被编译成 ES6 之前的 JavaScript。例如,Babel 变成了这样:


import something from 'myModule';

...进入这个:


var _myModule = _interopRequireDefault(require("myModule"));


function _interopRequireDefault(obj) {

  return obj && obj.__esModule ?

    obj :  // <= return the result of require("myModule") if it is an ES6 module...

    { default: obj };  // <= otherwise set it to the default property of a wrapper object

}

...所以如果'myModule'是 ES6 模块,它会直接返回...但如果不是,则互操作返回一个包装对象。


由于每个import都有不同的包装对象,因此更改一个的default属性不会影响default任何其他对象的属性。


查看完整回答
反对 回复 2021-07-01
?
Helenr

TA贡献1780条经验 获得超4个赞

你可以自己制作一个包装文件,它最终会lodash/debounce为你导出同一个实例,但这次你可以存根,例如:


myutils/lodash/debounce.js


import lodashDebounce from 'lodash/debounce';


const exports = {

    debounce: lodashDebounce,

};


export const debounce = () => exports.debounce();


export default exports;

现在,在您的实际代码中,debounce不是从原始位置导入,而是从这个包装文件导入:


前:


import debounce from 'lodash/debounce' // this is how we usually do

后:


import { debounce } from 'myutils/lodash/debounce' // if we want to stub it



// all other code-lines remain the same

const method = () => {

    debounce(callback, 150));

    ...

}


现在在做test.js 时:


import lodashWrapped from 'myutils/lodash/debounce';


sinon.stub(lodashWrapped , 'debounce').callsFake((callbackFn) => {

  // this is stubbed now

});


// go on, make your tests now 


查看完整回答
反对 回复 2021-07-01
  • 2 回答
  • 0 关注
  • 184 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信