javascript 存根模块功能

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24274870/
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-10-28 02:29:18  来源:igfitidea点击:

Stub out module function

javascriptnode.jssinon

提问by mitchkman

Edit: Being a little bit more precise.

编辑:更精确一点。

I want to test usecases for a Github API wrapper extension, that our team has created. For testing, we don't want to use API wrapper extension directly, so we want to stub out its functions. All calls to the API wrapper should be stubbed out for the tests, not just creating a clone stub.

我想测试我们团队创建的 Github API 包装器扩展的用例。为了测试,我们不想直接使用 API 包装器扩展,所以我们想把它的函数存根。对 API 包装器的所有调用都应该被剔除以进行测试,而不仅仅是创建一个克隆存根。

I have a module "github" in Node.js:

我在 Node.js 中有一个模块“github”:

module.exports = function(args, done) {
    ...
}

And I am requiring it like this:

我要求它是这样的:

var github = require('../services/github');

Now, I would like to stub out github(...)using Sinon.js:

现在,我想github(...)使用 Sinon.js存根:

var stub_github = sinon.stub(???, "github", function (args, callback) { 
    console.log("the github(...) call was stubbed out!!");
});

But sinon.stub(...)expects from me to pass an object and a method and does not allow me to stub out a module that is a function.

但是sinon.stub(...)期望我传递一个对象和一个方法,并且不允许我将作为函数的模块存根。

Any ideas?

有任何想法吗?

采纳答案by Retsam

There might be a way to accomplish this in pure Sinon, but I suspect it would be pretty hacky. However, proxyquireis a node library that is designed for solving these sort of issues.

可能有一种方法可以在纯 Sinon 中完成此操作,但我怀疑它会非常笨拙。但是,proxyquire是一个节点库,旨在解决此类问题。

Supposing you want to test some module foothat makes use of the github module; you'd write something like:

假设您要测试某个foo使用 github 模块的模块;你会写这样的:

var proxyquire = require("proxyquire");
var foo = proxyquire(".foo", {"./github", myFakeGithubStub});

where myFakeGithubStubcan be anything; a complete stub, or the actual implementation with a few tweaks, etc.

哪里myFakeGithubStub可以是任何东西;一个完整的存根,或经过一些调整的实际实现,等等。

If, in the above example, myFakeGithubStubhas a property "@global" set as true, (i.e. by executing myFakeGithubStub["@global"] = true) then the github module will be replaced with the stub not only in the foomodule itself, but in any module that the foomodule requires. However, as stated in the proxyquire documentation on the global option, generally speaking this feature is a sign of poorly designed unit tests and should be avoided.

如果在上面的示例中,myFakeGithubStub将属性“@global”设置为 true(即通过执行myFakeGithubStub["@global"] = true),那么 github 模块将被替换为存根,不仅在foo模块本身中,而且在foo模块需要的任何模块中。但是,正如有关 global optionproxyquire 文档中所述,一般而言,此功能是单元测试设计不佳的标志,应避免使用。

回答by Ben Davies

I found that this worked for me...

我发现这对我有用......

const sinon          = require( 'sinon' );
const moduleFunction = require( 'moduleFunction' );

//    Required modules get added require.cache. 
//    The property name of the object containing the module in require.cache is 
//    the fully qualified path of the module e.g. '/Users/Bill/project/node_modules/moduleFunction/index.js'
//    You can get the fully qualified path of a module from require.resolve
//    The reference to the module itself is the exports property

const stubbedModule = sinon.stub( require.cache[ require.resolve( 'moduleFunction' ) ], 'exports', () => {

    //    this function will replace the module

    return 'I\'m stubbed!';
});

// sidenote - stubbedModule.default references the original module...

You have to make sure that you stub the module (as above) before it's required elsewhere...

您必须确保在其他地方需要之前将模块存根(如上所述)......

// elsewhere...

const moduleFunction = require( 'moduleFunction' ); 

moduleFunction();    // returns 'I'm stubbed!'

回答by Demeter

Simplest solution is to refactor your module:

最简单的解决方案是重构你的模块:

instead of this:

而不是这个:

module.exports = function(args, done) {
    ...
}

do this:

做这个:

module.exports = function(){
    return module.exports.github.apply(this, arguments);
};
module.exports.github = github;

function github(args, done) {
    ...
}

Now you can require it with:

现在您可以使用以下命令来要求它:

const github = require('../services/github.js');
//or
const github = require('../services/github.js').github;

To stub:

存根:

const github = require('../services/github.js');
let githubStub = sinon.stub(github, 'github', function () {
    ... 
});

回答by blockchaining

If you are doing

如果你在做

var github = require('../services/github');

var github = require('../services/github');

in global scope, then you can using 'global' as the object and 'github' as the method to be stubbed out.

在全局范围内,您可以使用 'global' 作为对象,使用 'github' 作为要删除的方法。

var stub_github = sinon.stub(global, "github", function (args, callback) { 
    console.log("the github(...) call was stubbed out!!");
});