如何在 javascript 全局命名空间中存根/模拟函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4486324/
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
How can I stub/mock a function in the javascript global namespace
提问by tjjava
I'm trying to stub/mock/override a function call during testing which writes a log to a DB.
我试图在测试期间存根/模拟/覆盖一个函数调用,该函数调用将日志写入数据库。
function logit(msg) {
writeMessageToDb(msg);
}
function tryingToTestThisFunction(){
var error = processSomething();
if (error) {
logit(error);
}
}
I'd like logit()
to simply print to the console during testing...and doing a "isTesting()
" if/else block inside the logit()
function is not an option.
我想logit()
在测试期间简单地打印到控制台......并且isTesting()
在logit()
函数内执行“ ” if/else 块不是一种选择。
Is this possible without including some additional mocking framework. I'm currently using JsTestDriver
for unit testing and have not had a chance to evaluate any mocking frameworks. An ideal solution at the moment would be to handle this without another framework.
这是否可能不包含一些额外的模拟框架。我目前JsTestDriver
用于单元测试,还没有机会评估任何模拟框架。目前一个理想的解决方案是在没有其他框架的情况下处理这个问题。
回答by sivabudh
I use Jasmine and Sinon.js (using Coffeescript), here's how I stub out the confirm()method to, for example, just return true.
我使用 Jasmine 和 Sinon.js(使用 Coffeescript),下面是我如何将confirm()方法存根,例如,只返回 true。
beforeEach ->
@confirmStub = sinon.stub(window, 'confirm')
@confirmStub.returns(true)
afterEach ->
@confirmStub.restore()
回答by Gabriele Petrioli
In javascript the latest definition is the prevalent.
在 javascript 中,最新的定义是流行的。
so just redefine the logit method after the first definition.
所以只需在第一个定义后重新定义 logit 方法。
function logit(msg) {
console.log(msg);
}
example : http://www.jsfiddle.net/gaby/UeeQZ/
回答by bmiller
I have been working on exactly the same problem. The developers gave me an HTML5 app to test, so of course I can't change their code for testing. I decided to use qunitand sinon, along with sinon-qunit.
我一直在研究完全相同的问题。开发人员给了我一个 HTML5 应用程序来测试,所以我当然不能更改他们的测试代码。我决定使用qunit和sinon,以及 sinon-qunit 。
For a newb to JavaScript unit testing like me, I was going nuts with the sinon documentation and various examples on the web, as most of it seems for an implied environment that isn't mentioned. The code below is a complete page, so I hope nothing is left for confusion.
对于像我这样的 JavaScript 单元测试新手,我对 sinon 文档和网络上的各种示例非常着迷,因为其中大部分内容似乎都用于未提及的隐含环境。下面的代码是一个完整的页面,所以我希望没有留下任何混淆。
The function that I have to call is caller()
and I can't do anything about stubme()
because it's in the developer's code. However, I can add sinonstub()
in my test code. But how to get it to work with sinon? The sinon documentation really confused me for a while, but below is the simple solution. The stub4stubme object can be used to control the stub action, and also get the information about what's happening with the stub calls.
我必须调用的函数是caller()
,我无能为力,stubme()
因为它在开发人员的代码中。但是,我可以添加sinonstub()
我的测试代码。但是如何让它与 sinon 一起工作呢?sinon 文档确实让我困惑了一段时间,但下面是简单的解决方案。stub4stubme 对象可用于控制存根操作,还可以获取有关存根调用发生情况的信息。
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="qunit-1.12.0.css" type="text/css" media="screen" />
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="sinon-1.7.3.js"></script>
<script src="qunit-1.12.0.js"></script>
<script src="sinon-qunit-0.8.0.js"></script>
<script>
// Dev code in another file
function stubme() {
return "stubme";
}
function caller() {
return "caller " + stubme();
}
// End of dev code
var sinonstub = function () {
return "u haz bin stubbed";
};
test("Stubbing global environments", function () {
equal(caller(), "caller stubme");
var stub4stubme = this.stub(window, "stubme", sinonstub);
equal(caller(), "caller u haz bin stubbed");
ok(stubme.called);
});
</script>
</body>
</html>
回答by Lance Kind
Javascript is not only runtimelinked, but is the last word winslinked as well. This means you can redeclare the method with the behavior you want in your test (since your test has the last word):
Javascript 不仅是运行时链接的,也是最后一个词 wins链接的。这意味着您可以在测试中使用您想要的行为重新声明该方法(因为您的测试具有最后一个词):
function yourTest(){
oldImpl = logit; // An even better approach is to do this in a setup.
logit = function(msg){ Console.log.apply(console, s.call(arguments));};
// do you assertions: assert.... yada.
logit = oldImpl; // Do this to keep your test isolated from the others you'll be executing in this test run. An even better approach is to do this in a teardown.
}
回答by hvgotcodes
can you just override the method on the window object? In Chrome console this works
你能覆盖window对象上的方法吗?在 Chrome 控制台中,这有效
function test() {console.log('test')};
window.test();
回答by Tracker1
just override the logit function, this can be called anytime later than logit is defined.
只需覆盖 logit 函数,就可以在定义 logit 之后的任何时间调用它。
(function(){
//keep handle to original logit method.
var ol = logit;
//shorter lookup path for slice
var s = Array.prototype.slice;
//logit override
logit = function() {
//if in testing
if (typeof IsTesting == "function" && !!IsTesting()) {
//log the arguments
console.log.apply(console, s.call(arguments));
} else {
//otherwise, call the original function.
ol.apply(this, s.call(arguments))
}
}
}());