Javascript 如何在 ES6 中存根导出的函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34575750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:34:42  来源:igfitidea点击:

How to stub exported function in ES6?

javascriptecmascript-6

提问by Mike Chaliy

I have file foo.js:

我有文件 foo.js:

export function bar (m) {
  console.log(m);
}

And another file that uses foo.js, cap.js:

另一个使用 foo.js 的文件 cap.js:

import { bar } from 'foo';

export default m => {
  // Some logic that I need to test
  bar(m);
}

I have test.js:

我有 test.js:

import cap from 'cap'

describe('cap', () => {
  it('should bar', () => {
      cap('some');
  });
});

Somehow I need override implementation of bar(m)in test. Is there any way to do this?

不知何故,我需要覆盖bar(m)测试中的实现。有没有办法做到这一点?

P.S. I use babel, webpack and mocha.

PS 我使用 babel、webpack 和 mocha。

回答by Mike Chaliy

Ouch.. I found solution, so I use sinonto stub and import * as foo from 'foo'to get object with all exported functions so I can stub them.

哎哟..我找到了解决方案,所以我使用sinon存根并import * as foo from 'foo'获取所有导出函数的对象,以便我可以存根它们。

import sinon from 'sinon';
import cap from 'cap';
import * as foo from 'foo';

sinon.stub(foo, 'bar', m => {
    console.log('confirm', m);
});

describe('cap', () => {
  it('should bar', () => {
    cap('some');
  });
});

回答by DreamSonic

You can replace/rewrite/stub exports only from within the module itself. (Here's an explanation)

您只能从模块本身内部替换/重写/存根导出。(这里有一个解释

If you rewrite 'foo.js' like this:

如果你像这样重写'foo.js':

var bar = function bar (m) {
  console.log(m);
};

export {bar}

export function stub($stub) {
  bar = $stub;
}

You can then override it in your test like this:

然后,您可以像这样在测试中覆盖它:

import cap from 'cap'
import {stub} from 'foo'

describe('cap', () => {
  it('should bar', () => {
      stub(() => console.log('stubbed'));
      cap('some'); // will output 'stubbed' in the console instead of 'some'
  });
});

I've created a Babel plugin that transforms all the exports automatically so that they can be stubbed: https://github.com/asapach/babel-plugin-rewire-exports

我创建了一个 Babel 插件,可以自动转换所有导出,以便它们可以被存根:https: //github.com/asapach/babel-plugin-rewire-exports

回答by Daniel Conde Marin

While @Mike solution would work in old versions of sinon, it has been removed since sinon 3.0.0.

虽然@Mike 解决方案适用于旧版本的 sinon,但它已从 sinon 3.0.0 中删除。

Now instead of:

现在代替:

sinon.stub(obj, "meth", fn);

you should do:

你应该做:

stub(obj, 'meth').callsFake(fn)

Example of mocking google oauth api:

模拟 google oauth api 的示例:

import google from 'googleapis';

const oauth2Stub = sinon.stub(); 

sinon.stub(google, 'oauth2').callsFake(oauth2Stub);

oauth2Stub.withArgs('v2').returns({
    tokeninfo: (accessToken, params, callback) => {
        callback(null, { email: '[email protected]' }); // callback with expected result
    }
});

回答by qff

You can use babel-plugin-rewire(npm install --save-dev babel-plugin-rewire)

你可以使用babel-plugin-rewire( npm install --save-dev babel-plugin-rewire)

And then in test.jsuse the __Rewire__function on the imported module to replace the function in that module:

然后test.js使用__Rewire__导入模块上的函数来替换该模块中的函数:

// test.js
import sinon from 'sinon'

import cap from 'cap'

describe('cap', () => {
  it('should bar', () => {
    const barStub = sinon.stub().returns(42);
    cap.__Rewire__('bar', barStub); // <-- Magic happens here
    cap('some');
    expect(barStub.calledOnce).to.be.true;
  });
});

Be sure to add rewireto your babel plugins in .babelrc:

一定要添加rewire到你的 babel 插件中.babelrc

// .babelrc
{
  "presets": [
    "es2015"
  ],
  "plugins": [],
  "env": {
    "test": {
      "plugins": [
        "rewire"
      ]
    }
  }
}

Lastly, as you can see the babel-plugin-rewireplugin is only enabled in the test environment, so you should call you test runner with the BABEL_ENVenvironment variable set to test(which you're probably doing already):

最后,正如您所看到的,该babel-plugin-rewire插件仅在测试环境中启用,因此您应该调用测试运行程序并将BABEL_ENV环境变量设置为test(您可能已经这样做了):

env BABEL_ENV=test mocha --compilers js:babel-core/register test-example.js

Note: I couldn't get babel-plugin-rewire-exportsto work.

注意:我无法babel-plugin-rewire-exports上班。