私はいくつかのJavaScriptをJasmineで単体テストし、jQueryセレクターによってアクセスされるDOMの要素をスパイ(モック)したいと思っています。
私の仕様は:
it("should be able to mock DOM call", function() {
spyOn($("#Something"), 'val').andReturn("bar");
result = $("#Something").val();
expect(result).toEqual("bar");
});
私のspecrunner.htmlには次のものがあります。
<input type="hidden" id="Something" value="foo" />
残念ながら、仕様は次のように失敗します。
dOM呼び出しをモックできるはずです。「foo」が「bar」に等しいと予想されます。
この行は間違っています:
spyOn($("#Something"), 'val').andReturn("bar");
JasmineのspyOn関数は2つのパラメーターを想定しています。最初は既存のオブジェクトです。 2番目は文字列としての関数名です。関数名を文字列( "val")として正しく渡しますが、既存のオブジェクトを最初のパラメーターとして渡しません。
$("#Something")
...は既存のオブジェクトではありません。 jQueryセレクターの結果(戻り値)です。より具体的には、一致したノードを表すjQueryオブジェクトを返します-一種の結果の配列のようなものです。
$
...は既存のオブジェクトです。
$.fn
...は既存のオブジェクトです。
$("#Something")
...はnot既存のオブジェクトです-それはjQueryセレクターの結果です。
これは動作します:
it("should be able to mock DOM call", function () {
//spyOn($.fn, "val").andReturn("bar"); //pre-jasmine 2.0 syntax
spyOn($.fn, "val").and.returnValue("bar"); //Jasmine 2.0 Syntax
var result = $("#Something").val();
expect(result).toEqual("bar");
});
良い解決策を見つけたようです
it "should open past statuses", ->
# We can't use $('.past') here cause each time $('.past') called it returns different objects
# so we need to store spy in variable
showSpy = spyOn($.fn, 'show')
# do the stuff
$('.show-past').click()
# then check if 'show' action was called
expect($.fn.show).toHaveBeenCalled()
# and if it realy our object
expect(showSpy.mostRecentCall.object.selector).toEqual('.past')
これはあなたのコードに基づいていませんが、これが誰かを助けることを願っています。そして、はい、CoffeScriptの例です。
問題は、$への2つの呼び出しが2つの異なるjQueryでラップされたノードを返すことです。
これは動作するはずです:
it("should be able to mock DOM call", function(){
// var node = $("Something");
// spyOn(node, 'val').andReturn('bar');
// expect(node.val()).toEqual('bar');
var node = $("Something");
spyOn(node, 'val').and.returnValue('bar');
expect(node.val()).toEqual('bar');
});
次回は、Jasmineメーリングリスト[email protected]でヘルプがより一般的になります。
独自の偽のDOM要素を作成し、通常どおり$( '#elementid')[0]を使用できます。
addFakeElementWithId = function (elementId) {
var fake = document.createElement("div");
fake.setAttribute("id", elementId);
document.body.appendChild(fake);
};
Id/value-pairsの配列を受け入れるヘルパー関数を作成しました。
_var jasminTestHelper = {
spyOnValAndFake : function(obj) {
var i, j;
spyOn($.fn, 'val').andCallFake(function() {
for ( i = 0, j = obj.length; i < j; i++) {
if (this.selector === '#' + obj[i][0]) {
return obj[i][1];
}
}
})
}
}
_
各ペアは、jQuery-val()関数がid-selectorで呼び出された場合にどのidに対してどの値が返されるべきかをfaker-functionに伝えます。次のように使用されます。
_jasminTestHelper.spyOnValAndFake([["id1", "value1"], ["id2", "value2"]]);
_
テスト対象の関数で$('#id1').val()
が呼び出された場合、fake-functionは_value1
_を返し、$('#id2').val()
が呼び出された場合は_value2
_を返します。したがって、DOMをいじる必要はなく、jQuery-val()関数をモックし、戻り値をシミュレートするだけです。他のjQuery関数もおそらく同じようにモックできます。
私のジャスミンバージョン(2.0.3)に変更があると思うので、Alex Yorkのソリューションはそのままでは機能しませんでしたが、間違いなく道を譲りました。だからここにテストする作業仕様jqueryコードがあります
$('someSelector').data('someAttribute').enable();
ここにジャスミン仕様の一部があります
var mockJqueryObject = { enable:function(){},disable:function(){}};
//this mocks the .data('someAttribute') in above code.
spyOn($.fn, "data").and.returnValue(mockSelectBoxObject);
より詳細な仕様では、別のレベルのモックを次のように使用できます。
spyOn(mockJqueryObject,"enable")
spyOn(mockJqueryObject,"disable")