如何测试调用 AJAX 函数而不使用 jasmine 触发它的函数?
How do I test a function that calls an AJAX function without firing it using jasmine?
我已经检查过 How do I verify jQuery AJAX events with Jasmine? and How to test an Angular controller with a function that makes an AJAX call without mocking the AJAX call?,但出于某种原因,他们不一定会提供适合我的格式。
我的问题是我正在对一个函数进行单元测试,该函数调用一个触发 AJAX 请求的函数。我想在不触发 AJAX 请求(或停止该请求)的情况下测试外部函数,这样我就不会将一堆错误数据发送到数据服务器中。
这是我的外部函数(调用包含 AJAX 的函数):
vm.clickSubmit = function () {
vm.loading = true; // starts the loading spinner
vm.updateData(); // makes current data current in the data model
vm.inputData = { // build the data to be submitted
...
};
vm.submit(); // calls the AJAX function
};
这是我的 AJAX 函数:
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();
});
};
我已经编写了所有将读取和验证 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()
的调用时加载微调器上的 expect 之后应该做什么?
谢谢,
-C§
我建议模拟调用而不是实际调用它。粒度由您决定,您可以对 ajax 调用进行存根,或者对整个提交函数进行存根。
以下是如何存根提交函数:
spyOn(controller, 'submit').and.callFake(function() {
DataService.ticketNumber = somevalue;
});
将该代码放在实际调用 caller.clickSubmit() 的控制器之前。
然后可以跟进对间谍的期望,比如:
expect(controller.submit).toHaveBeenCalled()
或与 spyOn 相关的任何其他期望。
这是茉莉花文档:http://jasmine.github.io/2.0/introduction.html
在'spies'区往下看
如果你想模拟 ajax 调用,你将不得不像这样模拟一个承诺:
spyOn($, 'ajax').and.callFake(function() {
var deferred = $q.defer();
deferred.resolve(someResponse);
return deferred.promise;
});
此外,为了让代码等待 promise 解析,在提交调用完成后,您需要 运行 一个 $scope.$digest() 以便 angular 可以处理承诺决议。然后您可以检查您对取决于承诺的解决或拒绝的代码的期望。
我已经检查过 How do I verify jQuery AJAX events with Jasmine? and How to test an Angular controller with a function that makes an AJAX call without mocking the AJAX call?,但出于某种原因,他们不一定会提供适合我的格式。
我的问题是我正在对一个函数进行单元测试,该函数调用一个触发 AJAX 请求的函数。我想在不触发 AJAX 请求(或停止该请求)的情况下测试外部函数,这样我就不会将一堆错误数据发送到数据服务器中。
这是我的外部函数(调用包含 AJAX 的函数):
vm.clickSubmit = function () {
vm.loading = true; // starts the loading spinner
vm.updateData(); // makes current data current in the data model
vm.inputData = { // build the data to be submitted
...
};
vm.submit(); // calls the AJAX function
};
这是我的 AJAX 函数:
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();
});
};
我已经编写了所有将读取和验证 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()
的调用时加载微调器上的 expect 之后应该做什么?
谢谢,
-C§
我建议模拟调用而不是实际调用它。粒度由您决定,您可以对 ajax 调用进行存根,或者对整个提交函数进行存根。
以下是如何存根提交函数:
spyOn(controller, 'submit').and.callFake(function() {
DataService.ticketNumber = somevalue;
});
将该代码放在实际调用 caller.clickSubmit() 的控制器之前。
然后可以跟进对间谍的期望,比如:
expect(controller.submit).toHaveBeenCalled()
或与 spyOn 相关的任何其他期望。
这是茉莉花文档:http://jasmine.github.io/2.0/introduction.html
在'spies'区往下看
如果你想模拟 ajax 调用,你将不得不像这样模拟一个承诺:
spyOn($, 'ajax').and.callFake(function() {
var deferred = $q.defer();
deferred.resolve(someResponse);
return deferred.promise;
});
此外,为了让代码等待 promise 解析,在提交调用完成后,您需要 运行 一个 $scope.$digest() 以便 angular 可以处理承诺决议。然后您可以检查您对取决于承诺的解决或拒绝的代码的期望。