How can I stub/mock a function in the javascript global namespace

爷,独闯天下 提交于 2019-12-23 06:57:53

问题


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.

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.


回答1:


I use Jasmine and Sinon.js (using Coffeescript), here's how I stub out the confirm() method to, for example, just return true.

beforeEach ->
  @confirmStub = sinon.stub(window, 'confirm')
  @confirmStub.returns(true)

afterEach ->
  @confirmStub.restore()



回答2:


In javascript the latest definition is the prevalent.

so just redefine the logit method after the first definition.

function logit(msg) {
  console.log(msg);
}

example : http://www.jsfiddle.net/gaby/UeeQZ/




回答3:


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 qunit and sinon, along with 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.

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.

<!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>



回答4:


can you just override the method on the window object? In Chrome console this works

function test() {console.log('test')};
window.test();



回答5:


just override the logit function, this can be called anytime later than logit is defined.

(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))
    }
  }
}());



回答6:


Because in Javascript is not only runtime linked, but the last word wins linked, just redeclare the method with the behavior you want in your test:

function yourTest(){
    oldImpl = logit;   // better to use 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. Better to use a tear down.
}


来源:https://stackoverflow.com/questions/4486324/how-can-i-stub-mock-a-function-in-the-javascript-global-namespace

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!