簡體   English   中英

如何在 javascript 全局命名空間中存根/模擬函數

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

我試圖在將日志寫入數據庫的測試期間存根/模擬/覆蓋函數調用。

function logit(msg) {
  writeMessageToDb(msg);
}

function tryingToTestThisFunction(){
  var error = processSomething();
  if (error) {
    logit(error);
  }
}

我希望logit()在測試期間簡單地打印到控制台......並且在logit()函數中執行“ isTesting() ” if/else 塊不是一個選項。

這是否可能不包含一些額外的模擬框架。 我目前正在使用JsTestDriver進行單元測試,還沒有機會評估任何模擬框架。 目前一個理想的解決方案是在沒有其他框架的情況下處理這個問題。

我使用 Jasmine 和 Sinon.js(使用 Coffeescript),下面是我如何將confirm()方法存根,例如,只返回 true。

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

afterEach ->
  @confirmStub.restore()

在 javascript 中,最新的定義是流行的。

所以只需在第一個定義之后重新定義 logit 方法。

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

示例: http : //www.jsfiddle.net/gaby/UeeQZ/

我一直在研究完全相同的問題。 開發人員給了我一個 HTML5 應用程序來測試,所以我當然不能更改他們的測試代碼。 我決定使用qunitsinon ,以及 sinon-qunit 。

對於像我這樣的 JavaScript 單元測試新手,我對 sinon 文檔和網絡上的各種示例非常着迷,因為其中大部分內容似乎都用於未提及的隱含環境。 下面的代碼是一個完整的頁面,所以我希望沒有留下任何混淆。

我必須調用的函數是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>

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.
}

你能覆蓋window對象上的方法嗎? 在 Chrome 控制台中,這有效

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

只需覆蓋 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))
    }
  }
}());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM