最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Stubbing single exported function with Sinon - Stack Overflow

programmeradmin4浏览0评论

I have just changed my lodash import from import _ from 'lodash'; to import debounce from 'lodash/debounce';
In my test I used to have sandbox.stub(_, 'debounce').returnsArg(0);, but now I'm stuck as to what to change it to. Obviously sandbox.stub(debounce).returnsArg(0); won't work. Not sure what to do when only a single function is exported from a module.

I have just changed my lodash import from import _ from 'lodash'; to import debounce from 'lodash/debounce';
In my test I used to have sandbox.stub(_, 'debounce').returnsArg(0);, but now I'm stuck as to what to change it to. Obviously sandbox.stub(debounce).returnsArg(0); won't work. Not sure what to do when only a single function is exported from a module.

Share Improve this question asked Jun 14, 2019 at 9:20 VotemikeVotemike 9022 gold badges13 silver badges34 bronze badges 1
  • Does this answer your question? How to stub exported function in ES6? – david_adler Commented Jul 26, 2021 at 8:44
Add a ment  | 

2 Answers 2

Reset to default 13

This syntax:

import something from 'myModule';

...is ES6 syntax which binds something to the default export of 'myModule'.

If the module is an ES6 module then you can stub the default export of the module like this:

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.

In this case 'lodash/debounce' is not an ES6 module, it is shipped pre-piled. 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.

Sinon doesn't provide module-level mocking so you will need to use something like 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.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 pilation.

ES6 syntax gets piled into pre-ES6 JavaScript. For example, Babel turns this:

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.

Since each import gets a different wrapping object, changing the default property on one doesn't affect the default property of any others.

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, e.g.:

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:

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:

import lodashWrapped from 'myutils/lodash/debounce';

sinon.stub(lodashWrapped , 'debounce').callsFake((callbackFn) => {
  // this is stubbed now
});

// go on, make your tests now 
发布评论

评论列表(0)

  1. 暂无评论