2012-01-19 9 views
36

ウィンドウオブジェクトを模擬するにはどうすればよいですか?私はfirefoxの拡張機能をやっていて、ジャスミンを使ってジャバスクリプトをテストしたい。ジャスミン模擬ウィンドウオブジェクト

window.openDialog

から任意のパラメータを渡していない場合は、そのオブジェクトが存在しないので、私は

 

function submit() { 
... 
var url = window.arguments[0]; 
... 
} 
 

はもちろん、私はジャスミンに[0] window.argumentsを模擬しなければならないしている私のJavaScriptで

これは

 

it("should submit to server", function() { 

     var localContext = { 
      "window": { 
       arguments: ["http://localhost"] 
      } 

     } 

     with(localContext); 
 

「と」とそれを嘲笑する私の試みです。しかし、私はまだ、このエラーTypeError例外を取得:プロパティを読み取ることができません「0」未定義の、それはテストがwindo実行されたときのようなものです私は、テスト内

window.arguments[0]

をすれば、それが出て印刷しますので、[0] w.argumentsは、実際の窓を払拭ます "のhttp:// localhost" を正しく。しかし、submit()メソッドの場合、window.argumentが定義されていないというエラーが表示されます。

答えて

52

問題は、ウィンドウオブジェクトのプロパティを上書きするだけです。あなたがそれを行うことができれば、ブラウザも同様にそれを行うことができます。だから誰でもアクセスできるグローバルオブジェクトの関数やプロパティを嘲笑するのは良い考えではありません。なぜなら、アクセスしようとしたときにあなたの変更がそこにあることを決して確信できないからです。

これは私にdependency injectionをもたらします。あなたのコードユニットをテスト可能にするための一般的なパターンは、ユニットに焦点を当てています。それはどういう意味ですか?新しいオブジェクトを作成したりグローバルオブジェクトにアクセスしたりするときは、ユニットの機能だけでなく、新しく作成したオブジェクトやグローバルオブジェクトの機能もテストしています。その前に、新しいオブジェクトをユニットに作成せずに渡します。通常はコンストラクタでこれを行いますが、JavaScript関数のように関数本体をコンストラクタとして持つオブジェクトもあるので、依存関係を関数に渡すこともできます。

あなたのケースでは、関数はグローバルウィンドウオブジェクトに依存します。そのため、グローバルウィンドウオブジェクトにアクセスするのではなく、それを関数としてパラメータとして渡します。それをあなたがあなたの製品コードと引数を持つシンプルなJavaScriptオブジェクトでウィンドウオブジェクトを渡すことができますこの方法をやって、あなたのテストにatribute:

youWannaTest(window); 
:あなたの拡張機能で

function youWannaTest(w){ 
    console.log(w.arguments[0]); 
} 

は、このような関数を呼び出しますテストで

は次のように関数を呼び出す:

youWannaTest({arguments: ['someValue']}); 
+0

感謝をブロックするので、私はそれをモックアップすることはできません:あなたのspecファイルになりました

var window = { arguments : ['url'] }; 

その後、あなたはコードの下に使用してウィンドウを模擬することができますか? – toy

+0

ポイントを少し明確にするために私の答えを更新しました。 –

1

私も依存性の注入がきれいな解決策だと思います。

あなたのJS:

function submit(_window) { 
    _window = _window || window 
    ... 
    var url = _window.arguments[0]; 
    ... 
} 

あなたのユニットテスト:

it('works like a dream', function() { 
    var _window = { arguments: ['url'] } 
    expect(submit(_window)).toBeTotallyAwesome() 
}) 
0

はい、あなたはウィンドウオブジェクトを模擬することができます。$ウィンドウウィンドウを交換してください:あなたがしなければならないだろう

最初の事はあなたのJSコード内の1つの変更を行うことです。 beforeEachに返信用

$controller('controllerName', {$window : window});