[英]Stubbing single exported function with Sinon
I have just changed my lodash import from import _ from 'lodash';
我刚刚改变了我的 lodash import from import _ from 'lodash';
to import debounce from 'lodash/debounce';
import debounce from 'lodash/debounce';
In my test I used to have sandbox.stub(_, 'debounce').returnsArg(0);
在我的测试中,我曾经使用过sandbox.stub(_, 'debounce').returnsArg(0);
, but now I'm stuck as to what to change it to. ,但现在我不知道将其更改为什么。 Obviously sandbox.stub(debounce).returnsArg(0);
显然sandbox.stub(debounce).returnsArg(0);
won't work.不会工作。 Not sure what to do when only a single function is exported from a module.当模块中只导出一个函数时,不确定该怎么做。
This syntax:此语法:
import something from 'myModule';
...is ES6 syntax which binds something
to the default
export of 'myModule
'. ...是 ES6 语法,它将something
内容绑定到'myModule
”的default
导出。
If the module is an ES6 module then you can stub the default
export of the module like this:如果模块是 ES6 模块,那么您可以像这样存根模块的default
导出:
import * as myModule from 'myModule';
const sinon = require('sinon');
// ...
const stub = sinon.stub(myModule, 'default');
...but this only works if 'myModule'
is an ES6 module. ...但这仅在'myModule'
是 ES6 模块时才有效。
In this case 'lodash/debounce'
is not an ES6 module, it is shipped pre-compiled.在这种情况下, 'lodash/debounce'
不是 ES6 模块,它是预编译的。 The last line is this:最后一行是这样的:
module.exports = debounce;
...which means the module export is the debounce function. ...这意味着模块导出是去抖动功能。
This means that in order to stub 'lodash/debounce'
you have to mock the entire module.这意味着为了存根'lodash/debounce'
你必须模拟整个模块。
Sinon doesn't provide module-level mocking so you will need to use something like proxyquire
: Sinon 不提供模块级模拟,因此您需要使用proxyquire
类的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 })
...or if you are using Jest
you can use something like jest.mock
: ...或者如果你使用Jest
你可以使用类似jest.mock
东西:
jest.mock('lodash/debounce', () =>
jest.fn((func, ms) => func) // <= mock debounce to simply return the function
);
Details细节
The reason that stubbing the default
export of a module only works if it is an ES6 module is because of what happens during compilation.仅当模块是 ES6 模块时才对模块的default
导出进行存根的原因是因为编译期间发生了什么。
ES6 syntax gets compiled into pre-ES6 JavaScript. ES6 语法被编译成 ES6 之前的 JavaScript。 For example, Babel turns this:例如,Babel 变成了这样:
import something from 'myModule';
...into this: ...进入这个:
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
}
...so if 'myModule'
is an ES6 module it gets returned directly...but if it is not then the interop returns a wrapping object. ...因此,如果'myModule'
是一个 ES6 模块,它将直接返回...但如果不是,则互操作返回一个包装对象。
Since each import
gets a different wrapping object, changing the default
property on one doesn't affect the default
property of any others.由于每一个import
都有不同的包装对象,更改default
的一个属性并不影响default
任何他人财产。
you can make yourself a wrapping file, which will eventually export the same lodash/debounce
instance for you, but this time you could stub that, eg:你可以自己制作一个包装文件,它最终会为你导出相同的lodash/debounce
实例,但这次你可以存根,例如:
myutils/lodash/debounce.js myutils/lodash/debounce.js
import lodashDebounce from 'lodash/debounce';
const exports = {
debounce: lodashDebounce,
};
export const debounce = () => exports.debounce();
export default exports;
now, in your actual code import the debounce
not from the original location, but from this wrapping file instead:现在,在您的实际代码中,不是从原始位置而是从这个包装文件导入debounce
:
BEFORE:前:
import debounce from 'lodash/debounce' // this is how we usually do
AFTER:后:
import { debounce } from 'myutils/lodash/debounce' // if we want to stub it
// all other code-lines remain the same
const method = () => {
debounce(callback, 150));
...
}
now when doing a test.js :现在在做test.js 时:
import lodashWrapped from 'myutils/lodash/debounce';
sinon.stub(lodashWrapped , 'debounce').callsFake((callbackFn) => {
// this is stubbed now
});
// go on, make your tests now
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.