我正在使用茉莉花进行单元测试,并使用sinon来模拟ajax调用。但是,这会导致无限循环,其中我的测试用例被重复调用。 ajax调用是同步进行的。如果我将ajax调用更改为异步,则不会发生无限循环。任何帮助或指示将不胜感激!
这是ajax调用的函数:
define([
// Utils
'util/logging',
// Project Dependencies
'views/core/baseView',
'i18n!i18n_DNA/nls/basePage',
'i18n!i18n_DNA/nls/consentSettingsView',
'duster!templates/widgets/testSettings/consentSettings.dust.html'
], function (Log, BaseView, i18n_basePage, i18n_consentSettingsView, template) {
'use strict';
// ConsentSettingsView
// -----------------------------------------------------------------------------------------
return BaseView.extend({
events: {
'click #deleteTestButton': 'deleteTestModal'
},
className: 'connectDelete',
// initialize()
// ---------------------------------------------------------------------------------------
initialize: function () {
this.hasConsented = this.options.hasConsented;
this.testId = this.options.testId;
this.appRouter = this.options.appRouter;
// Call `super()`.
BaseView.prototype.initialize.call(this);
},
// render()
// ---------------------------------------------------------------------------------------
render: function () {
var self = this;
var context = {
i18n_basePage: i18n_basePage,
i18n_consentSettingsView: i18n_consentSettingsView,
hasConsented: this.hasConsented,
testId: this.testId
};
dust.render('templates/widgets/testSettings/consentSettings.dust.html', context, function (err, out) {
if (err) {
console.error(err);
} else {
self.$el.html(out);
}
});
return self;
},
// deleteTestModal()
// ---------------------------------------------------------------------------------------
deleteTestModal: function () {
AcomModal.open('deleteTestModal');
$('#pDelId').click($.proxy( this.deleteTest, this));
},
// deleteTest()
// ---------------------------------------------------------------------------------------
deleteTest: function () {
var self = this;
$.ajax({
url: 'testSettings/' + encodeURIComponent(this.testId),
dataType: 'json',
data: {
password: $('#pUserPwd').val(),
testId: self.testId
},
async: false,
type: 'DELETE',
success: function (data, textStatus, jqXHR) {
Log.info("Successfully deleted test #", self.testId, data, textStatus, jqXHR);
},
error: function (jqXHR, textStatus, errorThrow) {
Log.error(jqXHR, textStatus, errorThrow);
switch (jqXHR.status) {
case 401:
self.appRouter.navigate("#login", {trigger: true});
break;
case 404:
self.appRouter.navigate("#404", {trigger: true});
break;
default:
self.appRouter.navigate("#serviceUnavailable", {trigger: true});
}
},
complete: function (jqXHR, textStatus) {
$('#pDelId').unbind('click');
window.location = window.location.origin + window.location.pathname + window.location.search;
}
});
}
});
});
这是我的测试用例:
define([
'backbone',
'views/widgets/testSettings/consentSettingsView'
], function (Backbone, ConsentSettingsView) {
// deleteTestModal()
// ---------------------------------------------------------------------------------------
describe('ConsentSettingsView.deleteTest()', function () {
var server;
var appRouter;
var consentSettingsView;
// Setup
// -----------------------------------------------------------------------------------------
beforeEach(function(){
appRouter = {
navigate: function () {
console.log('navigate called', arguments);
}
};
consentSettingsView = new ConsentSettingsView({
hasConsented: false,
testId: 1,
appRouter: appRouter
});
server = sinon.fakeServer.create();
server.respondWith(/testSettings\/(\d+)/, function(xhr, id) {
switch (id) {
case '1':
xhr.respond(200, {'Content-Type': 'application/json'}, JSON.stringify({id: id, success: true}));
break;
case '2':
xhr.respond(401, {'Content-Type': 'application/json'}, JSON.stringify({id: id, success: false}));
break;
case '3':
xhr.respond(404, {'Content-Type': 'application/json'}, JSON.stringify({id: id, success: false}));
break;
default:
xhr.respond(500, {'Content-Type': 'application/json'}, JSON.stringify({id: id, success: false}));
break;
}
});
});
afterEach(function(){
server.restore();
});
it('makes a successful ajax call', function () {
consentSettingsView.testId = 1;
consentSettingsView.deleteTest();
});
});
});
答案 0 :(得分:0)
如果你想进行异步测试,你需要使用Jasmine正确的方法进行异步测试,它们与同步不同,如果你现在将代码更改为异步,它将不会返回任何内容,那么你会发现奇怪的行为。 / p>
查看:http://pivotal.github.com/jasmine/#section-Asynchronous_Support
现在你的测试应该是这样的:
it('makes a successful ajax call', function () {
runs(function() {
consentSettingsView.testId = 1;
consentSettingsView.deleteTest();
});
var timeoutIn = 1000; // A second
waitFor(function() {
// Return something that flags your test is ok or not after the timeout time
}, 'No server response', timeoutIn);
runs(function() {
// Expected result to check from your test
});
});
个人我认为执行此异步测试的更好方法是更改方法deleteTest
,以便能够将回调作为参数传递,如promisses
模式:
deleteTest: function (success, fail) ....
然后你可以输入检查并在所需的上下文中运行,如下所示:
if (typeof success === 'function') { success.call(this); }
相同的失败,但在jQuery选项的ajax失败回调函数内。
现在您可以添加以下内容:
it('makes a successful ajax call', function () {
var result = false;
runs(function() {
consentSettingsView.testId = 1;
consentSettingsView.deleteTest(function () {
result = true;
}, function () {
result = false;
});
});
var timeoutIn = 1000; // A second
waitFor(function() {
return result;
}, 'No server response', timeoutIn);
runs(function() {
// Expected result to check from your test
expect(result).toBe(true);
});
});
在google中发帖查看,我发现了article。
他解释说我非常喜欢你,希望能帮到你。