Javascript 如何测试调用AJAX函数而不使用jasmine启动它的函数?
我已经登记了,但出于某种原因,他们不一定会拿出适合我的格式 我的问题是,我正在对一个函数进行单元测试,该函数调用发出AJAX请求的函数。我想在不触发AJAX请求(或停止该请求)的情况下测试外部功能,这样就不会将大量错误数据发送到数据服务器 下面是我的外部函数(它调用包含AJAX的函数): 以下是我的AJAX函数:Javascript 如何测试调用AJAX函数而不使用jasmine启动它的函数?,javascript,jquery,angularjs,unit-testing,karma-jasmine-ajax,Javascript,Jquery,Angularjs,Unit Testing,Karma Jasmine Ajax,我已经登记了,但出于某种原因,他们不一定会拿出适合我的格式 我的问题是,我正在对一个函数进行单元测试,该函数调用发出AJAX请求的函数。我想在不触发AJAX请求(或停止该请求)的情况下测试外部功能,这样就不会将大量错误数据发送到数据服务器 下面是我的外部函数(它调用包含AJAX的函数): 以下是我的AJAX函数: vm.submit = function () { var d = $.ajax({ type: "POST" , data: angular.
vm.submit = function () {
var d = $.ajax({
type: "POST"
, data: angular.toJson(vm.inputData)
, url: "http://submit_the_data"
, contentType: "application/json"
, xhrFields: { withCredentials: true }
, crossDomain: true
})
.success(function (resp) {
DataService.ticketNumber = resp; // returns ticket# for the data model
})
.error(function (error) {
DataService.ticketNumber = DataService.submitError;
});
d.then(function (d) {
vm.loading = false; // stops the loading spinner
DataService.tickets = []; // empty's the array to be filled anew
$location.path('/submitted'); // success splash html
$scope.$apply();
});
};
spyOn(controller, 'submit').and.callFake(function() {
DataService.ticketNumber = somevalue;
});
我已经编写了所有的测试来读取和验证inputData
对象中的值,但是我不确定如何调用clickSubmit()
,因此实际上没有向服务器提交任何内容。我在单元测试中已经达到了这一点:
'use strict';
describe('Controller: HomeController', function () {
beforeEach(module('tickets'));
var controller, scope, $location, DataService;
var tests = 0;
beforeEach(inject(function ($rootScope, $controller, _$location_, _DataService_) {
$location = _$location_;
DataService = _DataService_;
scope = $rootScope.$new();
controller = $controller('HomeController', {
$scope: scope
});
}));
afterEach(function () {
tests += 1;
});
describe('clickSubmit should verify data and submit new ticket', function () {
beforeEach(function () {
jasmine.Ajax.install();
controller.loading = false;
... // inputData fields filled in with test data
});
afterEach(function () {
jasmine.Ajax.uninstall();
});
it('should start the spinner when called', function () {
controller.clickSubmit();
expect(controller.loading).toBeTruthy();
});
// other it('') tests
});
it('should have tests', function () {
expect(tests).toBeGreaterThan(0);
});
});
那么,在加载微调器上,在实际代码中取消对vm.submit()
的调用之后应该做什么呢
谢谢
-C§我建议模拟呼叫,而不是实际呼叫。粒度由您决定,您可以存根ajax调用,也可以存根整个提交函数 以下是如何存根submit函数:
vm.submit = function () {
var d = $.ajax({
type: "POST"
, data: angular.toJson(vm.inputData)
, url: "http://submit_the_data"
, contentType: "application/json"
, xhrFields: { withCredentials: true }
, crossDomain: true
})
.success(function (resp) {
DataService.ticketNumber = resp; // returns ticket# for the data model
})
.error(function (error) {
DataService.ticketNumber = DataService.submitError;
});
d.then(function (d) {
vm.loading = false; // stops the loading spinner
DataService.tickets = []; // empty's the array to be filled anew
$location.path('/submitted'); // success splash html
$scope.$apply();
});
};
spyOn(controller, 'submit').and.callFake(function() {
DataService.ticketNumber = somevalue;
});
将该代码放在实际调用调用方的控制器之前。单击Submit()
然后,您可以跟进对间谍的期望,例如:
expect(controller.submit).toHaveBeenCalled()
或者任何其他与spyOn相关的期望
以下是茉莉花文档:俯视“间谍”区域 如果要模拟ajax调用,必须模拟这样的承诺:
spyOn($, 'ajax').and.callFake(function() {
var deferred = $q.defer();
deferred.resolve(someResponse);
return deferred.promise;
});
另外,为了让等待承诺解析的代码,在进行提交调用后,需要运行$scope.$digest(),以便angular能够处理承诺解析。然后,您可以检查您对依赖于承诺的解决方案或拒绝的代码的期望。在my
updateData()
function“error:预期是间谍,但获得了函数”上出现错误。在加载inputData块之后,我将spyOn
块放在每个之前的块中。这是这组测试中唯一失败的。expect(controller.submit).tohavebeencall()代码>已通过,因此我不明白为什么updateData()
测试失败。没关系,使用spyOn(控制器,'updateData')和.callThrough()使其工作代码>。谢谢你的帮助。在模拟数据服务时,我可能会经常提到这一点(自从我把这个从控制器中移出后,它现在有3个AJAX调用)解决了我自己的问题。我得到了错误“$q未定义”,并意识到我只需要像这样注入它:beforeach(inject(function($q){…}))我真的很感激你在这里为我提供的一切。谢谢,C§首先,我建议您将ajax调用转移到一个单独的服务中。看起来您现在只是将服务调用中的数据设置到角度服务/工厂中。然后您应该测试服务/工厂本身。Angular为此提供$httpBackend(),因此您不必实际调用该服务。对于控制器测试,您应该模拟服务/工厂,这样您就不必关心您的服务/工厂做了什么。@m.brand您是否介意在下面填写一个说明此方法的答案?我之所以这么问,是因为我对Angular/Jasmine/Karma还很陌生。另外,$httpBackend是否与引用的AJAX调用一起工作,还是必须将其转换为$http?谢谢,C§这个答案展示了将ajax调用拉入服务的两个解决方案: