2012-02-28 12 views
6

私はjQuery呼び出しをテストするためのオブジェクトの設定方法を理解するのに非常に苦労しています。私は非同期の呼び出しや何かを模倣する必要はありません、ちょうど基本的な使用。jQueryを使って基本的な使い方をテストする

listGamesCallback : function(data) { 
    var gameList = $("#gameList select"); 

    gameList.empty(); 

    $.each(data, function() { 
      var newOption = $('<option>', {value : this.gameId }); 
      newOption.text(string); 
      newOption.data("isJoinable", isJoinable); 

      // Add it to the list 
      gameList.append(newOption); 
    }); 


} 

は、私はユニットテスト、この方法には、ここでのjQueryを模擬する必要があるが、私はこれを行う方法を見つけ出すことができないよ:だから私は、私がテストしたい私の機能を設定してみましょう(簡単にするために切り捨て) JavaScriptで。 jsMockitoがなくても、jQueryがこのような状況にあるプロパティを持つオブジェクトを作成する方法はわかりません。これについての助けに感謝します。

私はjsTestDriver、jsHamcrest、jsMockito、jQueryを使用しています。しかし、これらのプロパティを持つ$オブジェクトを作成する一般的なアプローチも素晴らしいでしょう。ありがとうございました!

尋ねられた人のために、私はそれがちょっとした仕事のように思えたのですが、理由は分かりません。

var saved$ = $; 

var mockContruct = mockFunction(); 
var mockedGamelist = mock(jQuery); 
var mockedOption = mock(jQuery); 

mocked$ = (function() { 
    var test = function(name) { 
     var args = jQuery.makeArray(arguments); 
     return mockContruct.call(test, args); 
    }; 

    $.extend(test, $); 

    // This is what confuses me. This worked, but it's wierd 
    // It allows me to use the regular jQuery functions like 
    // $.each, while returning mocked objects when selectors are used. 
    test.prototype.constructor = test; 

    return test; 
})(); 

$ = mocked$;  

when(mockContruct).call(anything(), hasItem(containsString("#gameList"))) 
    .thenReturn(mockedGamelist); 

when(mockContruct).call(anything(), hasItems(containsString("<option>"), both(object()).and(hasMember("value")))) 
     .thenReturn(mockedOption); 

headerFunctions.listGamesCallback([ { 
    gameId : 1, 
    isWhitesTurn : false, 
    isGameOver : false, 
    whiteUserName : "foobar", 
    blackUserName : "barfoo" 
} ]); 

JsMockito.verify(mockedGamelist).empty(); 
JsMockito.verify(mockedGamelist).append(mockedOption); 

$ = saved$; 
+0

テストコードも入力しておけば便利です。 :) – alpian

+0

申し訳ありませんが、遅れて返信しましたが、私はこれが優先順位が低くなるように再割り当てされました。私は質問に編集したテストを実行する複雑な方法を持っています。 jQueryがどういう仕組みをしているのかよくわからないので、あまりよく書かれていません。 – CrazyBS

+0

あなたが書いたテストでは、あなたのコード以外のものは実際には実行されません。失敗した場合に$を復元しないため、失敗した場合には、問題のある他のテストも汚染される可能性があります。私はあなたがまだこれらのテストのポイントを見逃していると思います:**あなたはあなたのコードから期待している**動作**のためのテストを書かなければなりません。関数が実行されたら、Xのオプションを持つgameListの値が何であっても、それを証明することに焦点を当てたテストを書くべきです。 – alpian

答えて

1

ここで私が思いついたのは、最小限の設定で仕事をしています。 .extendは、jQueryオブジェクトが正しく設定されるように完全に必要です。これにより、テストを実行するために使用できるmocked jQueryオブジェクトを返すようにコンストラクタをモックできます。スパイとして、jQueryはあなたが何か他のことをしたいときを除いて、すべての状況で期待どおりに動作します。ここにあります:

TestCase("HeaderTest", { 
    testListGamesCallback : function() { 
     var saved$ = $; 

     $ = $.prototype.construct = jQuery.extend(spy(jQuery), jQuery); 

     var mockGameList = mock(jQuery); 
     when($)(containsString("#gameList")).thenReturn(mockGameList); 

     headerFunctions.listGamesCallback([ { 
      gameId : 1, 
      isWhitesTurn : false, 
      isGameOver : false, 
      whiteUserName : "foobar", 
      blackUserName : "barfoo" 
     } ]); 

     verify(mockGameList).empty(); 
     verify(mockGameList).append(object()); 

     $ = saved$; 
    } 
}); 

この解決策の注意点は、コンストラクタ以外のものを嘲笑するのはちょっと難しいことです。あなたは模擬したいそれぞれの個々の機能を設定し、その動作をプログラムしなければなりません。したがって:

$.each = mockFunction(); 
when($.each)(...matchers...).thenReturn(...); 

しかし、それでもあなたが必要とするものをテストすることができます。

0

私はあなたが何を意味するかを理解していますが、あなたたとえば「データ」を作成する場合、これは私が知っている方法である場合はNoを確認してください:

var data = [ { id : 1 , name : 'foo' } , { id : 2, name : 'bar' ] ​ 

しかし - あなたが作成したい場合オプションのリストは、あなたのコードよりも修正のカップルを必要とする: はjQueryのモックが何のためにあるのかないモックhttp://jsfiddle.net/7MMap/

var data = [ { gameId : 1 , name : 'foo' ,isJoinable:true} , { gameId : 2, name : 'bar' ,isJoinable:false}] 

    listGamesCallback = function(data) { 
    var gameList = $("#gameList select") 
        .empty(); 

    $.each(data, function(i,d) { 
      var newOption = $('<option>', {value : d.gameId }) 
      .text(d.name) 
      .data("isJoinable", d.isJoinable); 

      // Add it to the list 
      gameList.append(newOption); 
    }) 
      }; 

listGamesCallback(data); 
+0

実際、jQuery.each()関数を使用すると、 'this'で直接値にアクセスできます。そしてそれらのすべての.text().data()は、嘲笑を複雑にし、IMHOは読みにくくする。しかし、それはちょうど意見です。あなたのうまくフォーマットされた答えをありがとう。私はまだjQueryを模擬しようとしています。 – CrazyBS

0

を参照してください。オブジェクトのコラボレーターを嘲笑するだけです。 jQueryはいくつかのユーティリティを提供しています - それは協力者ではないので、嘲笑されるべきではありません。

あなたがここで協力しているのは、DOMまたはコードとDOMの中間オブジェクトです。 dataは値オブジェクトであり、Aviが示唆するようにテストで簡単に作成できます。

私のJSテストでは、私はDOMをモックしません、私は実際のDOMを使用し、私はテストの間に作成したものを壊すことを確認し、これはかなりうまくいくようです。

+0

私はこの状況での私のテストに同意します。しかし、私の考えは、テストをできるだけ孤立させたいから、jQueryが実際に何かをやってほしくないと思っていました。使用されたことを確認するだけです。ただし、これにはjQueryを常に使用してテストに合格する必要があります。だから、あなたはポイントを持っています。 – CrazyBS

+0

DOMを模擬することはできますか? – CrazyBS

+0

もちろん、あなたは**できますが、実際にはあなたのテストでは、本当のDOMにidというIDを持つREALを追加してから、あなたの関数を実行してから、それを実行した後にCSSセレクタを使って)DOMはそれを見ているように見えます。 jQueryを模擬しようとすることは忘れてください。それはユーティリティなので、それをする必要はありません。 – alpian

1

アルピアンの答えの拡張として、DOM要素をページに追加することなく作成できます。あなたのJSを作る機能は、パラメータとして、関連する要素を取る:

listGamesCallback : function(data, gameListSelectElem) { 
    var gameList = $(gameListSelectElem); 
    ... 

などのようにそれらをテスト:

var fakeSelect = $('<select>'), 
    data = ...; 

listGamesCallback(data, fakeSelect[0]); 

equal(fakeSelect.find('option').length, 1, 'must have exactly 1 option'); 
... 

上記のコードの最後の行がqUnitためです。必要なものはすべて取っておきましょう。要点は、ページに追加されなかったDOM要素を渡した後、jQueryを使用してDOM要素を調べて、正しく操作されたかどうかを調べることです。

関連する問題