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任何其他对象的属性。

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
添加回答
举报