繁体   English   中英

用 Sinon 存根单个导出函数

[英]Stubbing single exported function with Sinon

我刚刚改变了我的 lodash import from import _ from 'lodash'; import debounce from 'lodash/debounce';
在我的测试中,我曾经使用过sandbox.stub(_, 'debounce').returnsArg(0); ,但现在我不知道将其更改为什么。 显然sandbox.stub(debounce).returnsArg(0); 不会工作。 当模块中只导出一个函数时,不确定该怎么做。

此语法:

import something from 'myModule';

...是 ES6 语法,它将something内容绑定到'myModule ”的default导出。

如果模块是 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类的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
);

细节

仅当模块是 ES6 模块时才对模块的default导出进行存根的原因是因为编译期间发生了什么。

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任何他人财产。

你可以自己制作一个包装文件,它最终会为你导出相同的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 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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