2010-12-20 18 views
13

DBにログを書き込むテスト中に関数呼び出しをスタブ/モック/オーバーライドしようとしています。javascriptグローバル名前空間で関数をスタブ/モックする方法

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

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

私はlogit()は、単に...テストとlogit()関数内/ elseブロックがオプションでない場合は、「isTesting()」をやって中にコンソールに出力したいと思います。

追加のモッキングフレームワークを追加しなくてもこれが可能ですか?私は現在ユニットテストのためにJsTestDriverを使用していますが、どんなモッキングフレームワークも評価する機会はありませんでした。理想的な解決策は、別のフレームワークなしでこれを処理することです。

答えて

3

JavaScriptでは最新の定義が一般的です。

したがって、最初の定義の後にlogitメソッドを再定義してください。

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

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

1

あなただけのウィンドウオブジェクトのメソッドをオーバーライドすることができますか?クロームコンソールでは、これはここで、私はジャスミンとSinon.jsは(のCoffeeScriptを使用)を使用

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

の作品、私は、例えば、単にtrueを返すようにconfirm()メソッドを消し方法です。

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

afterEach -> 
    @confirmStub.restore() 
+2

このケースは異なっていますWindow.confirm()はグローバル関数ではありません。 –

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"をパラメーターとして指定して直接渡すことができます。メソッドの.applyを指定したs.call(引数)はすべてを通過させるため、このようなメソッドのオーバーライドの方が効果的です。 – Tracker1

1

私はまったく同じ問題に取り組んでいます。開発者はテストするHTML5アプリを私に渡したので、テスト用にコードを変更することはできません。私はqunitsinonをsinon-qunitと一緒に使うことに決めました。

私のようなnewb-to-JavaScriptユニットテストでは、ほとんどのものが暗黙環境ではないと思われるので、私はsinonのドキュメントとWeb上のさまざまなサンプルを使っていました。下のコードは完全なページなので、混乱の余地はありません。

私が呼び出さなければならない機能は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にあるかもしれないし、....でもそれはまだ "ウィンドウ"ですか? –

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. 
} 
関連する問題