2012-08-22 29 views
28

次はjavascriptの送信要求(1)のコードです。
ここでは、jasmine(2)を使用してajaxリクエストを嘲笑する方法について説明します。ジャスミンを使用して完了したフェイル遅延オブジェクトをテストする方法

私はサーバーの動作を模擬したいと思います。何か案は?
詳細については、(1)および(2)のコメントを参照してください。

P.S .:
実際には、どちらの場合でも、fakeFunctionの完了オブジェクトと失敗した遅延オブジェクトが呼び出されます。


(1)

submitForm: function() { 
    // the server execute fail only if message.val() is empty 
    // and I would like to mock this behaviour in (2) 
    backendController.submitForm(message.val()).done(this.onSuccess).fail(this.onError); 
}, 

backendController.submitForm = function (message) { 
    return $.ajax({ 
     url: 'some url', 
     type: 'POST', 
     dataType: 'json', 
     data: { 
      message: message 
     } 
    }).done(function() { 
     //some code; 
    }); 
}; 

(2)

describe('When Submit button handler fired', function() { 
    var submitFormSpy, 
     fakeFunction = function() { 
      this.done = function() { 
       return this; 
      }; 
      this.fail = function() { 
       return this; 
      }; 
      return this; 
     }; 

    beforeEach(function() { 
     submitFormSpy = spyOn(backendController, 'submitForm').andCallFake(fakeFunction); 
    }); 

    describe('if the message is empty', function() { 
     beforeEach(function() { 
      this.view.$el.find('#message').text(''); 
      this.view.$el.find('form').submit(); 
     }); 
     it('backendController.submitForm and fail Deferred Object should be called', function() { 
      expect(submitFormSpy).toHaveBeenCalled(); 
      // how should I test that fail Deferred Object is called? 
     }); 
    }); 

    describe('if the message is not empty', function() { 
     beforeEach(function() { 
      this.view.$el.find('#message').text('some text'); 
      this.view.$el.find('form').submit(); 
     }); 
     it('backendController.submitForm should be called and the fail Deferred Object should be not called', function() { 
      expect(submitFormSpy).toHaveBeenCalled(); 
      // how should I test that fail Deferred Object is not called? 
     }); 
    }); 

}); 
+0

は、はるかに簡単にそれらのテストを行います。ご意見をお寄せいただきありがとうございます。https://github.com/webadvanced/takeCommand – Paul

+1

@Paul実際には '/ webadvanced/takeCommand'をなぜ使うべきか正確に分かりません。なぜなら' $ .ajax'はすでに必要なものを持っているからです。サンプルコードを書いて私に答えることができますか? –

+0

var spy = spyOn(クラス、 "メソッド");actionThatCallsClassMethod(); expect(スパイ).toHaveBeenCalled(); あなたの例から私を助けました。 – Aligned

答えて

24

試してみてください。私たちのテストソリューションには、ジャスミン自体と組み合わせてJasmine-Ajaxライブラリを使用することが含まれます。

だから、おそらくそれはこのようなものになります:あなたは、あなたが全体のDOMツー応答コールバックパスをテストしていないような機能を分割しようとすることができるならば、

describe('When Submit button handler fired', function() { 
    jasmine.Ajax.useMock(); 

    describe('if the message is empty', function() { 

    beforeEach(function() { 
     spyOn(backendController, 'submitForm').andCallThrough(); 
     // replace with wherever your callbacks are defined 
     spyOn(this, 'onSuccess'); 
     spyOn(this, 'onFailure'); 
     this.view.$el.find('#message').text(''); 
     this.view.$el.find('form').submit(); 
    }); 

    it('backendController.submitForm and fail Deferred Object should be called', function() { 
     expect(backendController.submitForm).toHaveBeenCalledWith(''); 
     mostRecentAjaxRequest().response({ 
     status: 500, // or whatever response code you want 
     responseText: '' 
     }); 

     expect(this.onSuccess).not.toHaveBeenCalled(); 
     expect(this.onFailure).toHaveBeenCalled(); 
    }); 
}); 

もう一つは1つのテスト。きめ細かい場合は、テスト内でDeferredオブジェクト自体を使用して、非同期遅延解像度を実際にテストできます。

キーは実際にテスト内で遅延オブジェクトを使用するため、expectコールのスコープはまだitファンクションブロック内にあります。

describe('loadTemplate', function() { 
    it('passes back the response text', function() { 
    jasmine.Ajax.mock(); 
    loadTemplate('template-request').done(function(response) { 
     expect(response).toBe('foobar'); 
    }); 
    mostRecentAjaxRequest().response({ status:200, responseText:'foobar' }); 
    }); 
}); 
+0

これは確かに取るべきアプローチです - ジャスミンにはこれが組み込まれていることを知ってうれしいですが、qunitやその他のユニットテストフレームワークを使用している場合 - [sinon.js](http://sinonjs.org/)はこれらのスタブ/ fakeXHRなども同様です。 – gnarf

+0

jasmine-ajax 3.0の 'response'が' respondWith'に置き換えられていることに注意してください。[リリースノート](https://github.com/jasmine/jasmine-ajax/blob/master/release_notes/3.0.md) – ivarni

3

あなたがAJAXリクエスト約束オブジェクトとVARを持っていたかどうかをテストする方がはるかに簡単になります。その場合は、次の操作を実行できます。

it('should do an async thing', function() {  
    var mutex = 1; 
    var promF = jasmine.createSpy('prF'); 

    runs(function() { 
    var promise1 = $.ajax(); 
    promise1.always(function(){ 
     mutex--; 
    }); 
    promise1.fail(function(){ 
     promF(); 
    }); 
    }); 

    waitsFor(function(){ 
    return !mutex; 
    }, 'Fetch should end', 10000); 

    runs(function() { 
     expect(promF).toHaveBeenCalled(); 
    }); 
}); 

以下、あなたに合った未テストコードを投稿します。私はajax呼び出しが.submit()クラスから初期化されていると思いますか?おそらく、beforeEach()からではなく、runs()ブロックからajaxリクエストを初期化する必要がありますが、どちらを試してみるべきでしょう。

describe('When Submit button handler fired and city is defined', function() { 
    var ajaxRequestSpy, 
     failSpy, successSpy, alwaysSpy, 
     mutex; 
    beforeEach(function() { 
     ajaxRequestSpy = spyOn(backendController, 'ajaxRequest').andCallThrough(); 
     failSpy = spyOn(ajaxRequestSpy(), 'fail').andCallThrough() 
     successSpy = spyOn(ajaxRequestSpy(), 'success').andCallThrough(); 
     mutex = 1; // num of expected ajax queries 
     alwaysSpy = spyOn(ajaxRequestSpy(), 'always').andCallFake(function() { 
      mutex--; 
     }); 
     this.view = new MyView({ 
      el: $('<div><form>' + 
       '<input type="submit" value="Submit" />' + 
       '<input type="text" name="city">' + 
       '</form></div>') 
     }); 
     this.view.$el.find('form').submit(); 
    }); 
    it('backendController.ajaxRequest should be called', function() { 
     runs(function() { 
      // maybe init ajax here ? 
     }); 

     waitsFor(function() { 
      return !mutex; 
     }, 'ajax request should happen', 5000); 

     runs(function() { 
      expect(ajaxRequestSpy).toHaveBeenCalled(); // true 
      expect(failSpy).toHaveBeenCalled(); // Error: Expected spy fail 
              // to have been called. 
     }); 

    }); 
}); 

しかし、私はライン

failSpy = spyOn(ajaxRequestSpy(), 'fail').andCallThrough(); 

が何をしたいないことを確認していません。別のスパイにスパイすることは可能ですか?そしてもしそうなら、なぜあなたはスパイを呼んでいますか?たぶん、あなたは私たちが実際にオンザフライテンプレート用のテンプレートスクリプトをAJAXed表し繰延オブジェクトをテストしようとすると、同じ問題に遭遇した

failSpy = spyOn(ajaxRequestSpy, 'fail').andCallThrough(); 
13

ここで私はそれをどうしていますか。

本質的に、$ .ajaxオブジェクトはDeferredオブジェクトを返します。したがって、$ .ajaxを偵察してDeferredを返し、次にそれを手動で起動してを実行することができます。済()のコードであなたのAjaxの呼び出しのラッパーを使用してJavaScriptの

コード

Index.prototype.sendPositions = function() { 
    var me = this; 
    $.ajax({ 
    ... 
    }).done(function(data, textStatus, jqXHR) { 
    me.reload(); 
    }).fail(function(jqXHR, textStatus, errorThrown) { 
    console.log(errorThrown); 
    }); 
}; 

テスト

it("should reload the page after a successful ajax call", function(){ 
    var deferred = new jQuery.Deferred(); 
    spyOn($, 'ajax').andReturn(deferred); 
    spyOn(indexPage, 'reload'); 
    indexPage.sendPositions(); 
    deferred.resolve('test'); 
    expect(indexPage.reload).toHaveBeenCalled(); 
}); 
+2

PSは、deferred.resolve()を呼び出す代わりに、失敗したことを察知します。deferred.reject()コール – Tony

+0

非常に簡単、感謝! – dbrin

関連する問題