简体   繁体   English

用 Sinon 存根单个导出函数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM