2010-12-20 70 views
13

我試圖在將測試日誌寫入數據庫的過程中存根/模擬/覆蓋函數調用。我如何在JavaScript全局命名空間中存根/模擬一個函數

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

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

我想logit()簡單地打印到控制檯測試期間...和做一個「isTesting()」如果logit()函數內部/ else塊是不是一種選擇。

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

回答

3

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

所以只是在第一次定義之後重新定義logit方法。

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

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

1

可你只是重寫窗口對象的方法?在Chrome的控制檯這部作品

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

我用茉莉和Sinon.js(使用CoffeeScript的),這裏就是我踩滅的confirm()方法,例如,剛剛返回true。

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

afterEach -> 
    @confirmStub.restore() 
+2

這種情況是不同的因爲Window.confirm()不是全局函數。 – 2015-10-19 01:48:58

1

只是覆蓋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)) 
    } 
    } 
}());
+0

注意:你可以指定「msg」作爲參數並直接傳遞,s.call(參數)和方法上的.apply會傳遞所有的東西,這對於像這樣的方法覆蓋更好。 – Tracker1 2011-12-16 16:48:18

1

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

對於福利局像我這樣的JavaScript單元測試,我會堅果與興農文檔和各種例子在網絡上,因爲大多數似乎對於未提及一個隱含的環境。下面的代碼是一個完整的頁面,所以我希望沒有什麼是混亂。

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

你幾乎已經把我的困惑弄糊塗了。 Sinon.stub(窗口,「stubme」,sinonstub);爲什麼「窗口」是頂級對象名稱?這裏有一些關於全局變量環境的問題,在你的例子中它被稱爲窗口,因爲它在窗口中運行。但是原始的海報可能在Node.js中,或者... ...那麼它仍然是「窗口」呢? – 2015-10-19 01:52:29

0

因爲在Javascript不僅運行聯繫,但硬道理勝聯繫,只是重新聲明與您在您的測試需要的行爲的方法:

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. 
} 
相關問題