これは、javascript送信要求(1)に関するコードです。
これは、jasmine(2)を使用してajaxリクエストをモックするテストです。
サーバーの動作を模擬したいと思います。何か案は?
詳細については、(1)および(2)のコメントを参照してください。
PS:
実際にはどちらの場合も、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?
});
});
});
実際に同じ問題に遭遇し、オンザフライテンプレート作成のためにAJAXされたテンプレートスクリプトを表すDeferredオブジェクトをテストしようとしました。私たちのテストソリューションでは、 Jasmine-Ajax ライブラリをJasmine自体と組み合わせて使用します。
したがって、おそらく次のようになります。
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();
});
});
可能であれば、機能を分割して、DOMから応答へのコールバックパス全体を1つのテストでテストしないようにしてください。十分に細かい場合は、テスト内でDeferredオブジェクト自体を使用して、非同期のDeferred解決を実際にテストできます。
重要なのは、テスト自体の中で実際に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' });
});
});
これが私がどうやってそれを成し遂げたかです。
基本的に、$。ajaxオブジェクトはDeferredオブジェクトを返すため、$。ajaxをスパイしてDeferredを返し、それを手動でトリガーしてJavaScriptで.done()コードを実行できます。
コード
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();
});
Ajaxリクエストのpromiseオブジェクトを持つ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();
あなたがしたいことをします。別のスパイをスパイすることは可能ですか?もしそうなら、なぜあなたはスパイを呼んでいるのですか?たぶんあなたは試してみるべきです
failSpy = spyOn(ajaxRequestSpy, 'fail').andCallThrough();