我正在使用AngularJs控制器将数据从表单发送到Google表单。使用Jasmine我写了单元测试,这引起了下面的问题:
Error: Unsatisfied requests: POST http://localhost:5000/google-form
at Function.$httpBackend.verifyNoOutstandingExpectation
(.../angular-mocks/angular-mocks.js:1474:13)
在google搜索并在stackowerflow中浏览了一些questions之后,我决定发布这个问题,因为我找不到解决方案。
以下是您参考的代码:
角度控制器
/* global $ */
'use strict';
angular.module('myApp')
.controller('QuickMessageCtrl', ['$scope', function ($scope) {
$scope.quickMessageButtonText = 'Send';
$scope.quickMessage = {
name: '',
email: '',
content: '',
};
function setSubmittingIndicators() {
$scope.quickMessageButtonText = '';
$scope.submitting = true;
}
$scope.postQuickMessageToGoogle = _.throttle(function() {
setSubmittingIndicators();
$.ajax({
url: 'https://docs.google.com/forms/d/MyFormKey/formResponse',
data: {
'entry.3' : $scope.quickMessage.name,
'entry.1' : $scope.quickMessage.email,
'entry.0' : $scope.quickMessage.content
},
type: 'POST',
dataType: 'jsonp',
statusCode: {
200: function (){
//show succes message;
}
}
});
}, 500);
}]);
单元测试代码
'use strict';
describe('Controller: QuickMessageCtrl', function() {
var $httpBackend, $rootScope, $controller, scope, apiUrl;
beforeEach(module('myApp'));
beforeEach(inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
apiUrl = $injector.get('apiUrl');
$httpBackend.expect(
'POST',
apiUrl + 'google-form',
{'name': 'test', 'email': 'test@test.com', 'content': 'this is content'}
).respond(200);
$rootScope = $injector.get('$rootScope');
scope = $rootScope.$new();
$controller = $injector.get('$controller');
$controller('QuickMessageCtrl', { $scope: scope });
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
describe('Successful form submit', function() {
beforeEach(function() {
scope.quickMessageForm = { $valid: true };
scope.quickMessage.email = 'test@test.com';
scope.quickMessage.name = 'test';
scope.quickMessage.content = 'this is test';
scope.postQuickMessageToGoogle();
});
it('should set submitting indicators on submit', function() {
expect(scope.quickMessageButtonText).toBe('');
});
});
});
答案 0 :(得分:2)
您的测试表明模拟http后端应该在URL
处收到POSTapiUrl + 'google-form'
,如果出现错误消息,则为http://localhost:5000/google-form
。
但是您的控制器永远不会向该URL发送POST。它向https://docs.google.com/forms/d/MyFormKey/formResponse
发送POST。它并没有使用angular的$ http服务,而是使用jQuery在它的背后。
答案 1 :(得分:1)
正如@JB Nizet指出的那样,你使用的是jQuery而不是angular方法。实际上你应该重构一下你的代码。
它是一个great practice来保持分离,比如Controller from Service。在您的情况下,您在控制器内使用服务。我宁愿建议您创建一个服务,然后在您的控制器中导入该服务。所以基本上代码如下:
<强>控制器强>
/* global $ */
'use strict';
angular.module('myApp')
.controller('QuickMessageCtrl', ['$scope', 'MyNewService', function ($scope, MyNewService) {
$scope.quickMessageButtonText = 'Send';
$scope.quickMessage = {
name: '',
email: '',
content: '',
};
function resetFormData() {
$('#name').val('');
$('#email').val('');
$('#content').val('');
}
$scope.postQuickMessageToGoogle = _.throttle(function() {
setSubmittingIndicators();
MyNewService.sendQuickMessage(
$scope.quickMessage.name,
$scope.quickMessage.email,
$scope.quickMessage.content
)
.success(
//sucess Message
//can be as well a function that returns a status code
)
.error(
//error Message
);
}, 500);
}]);
<强>服务强>
'use strict';
angular.module('myApp')
.factory('MyNewService', ['$http', function ($http) {
var myService = {};
myService.sendQuickMessage = function(name, email, content) {
$http({
method: 'JSONP',
url: 'https://docs.google.com/forms/d/MyFormKey/formResponse?'+
'entry.3=' + name +
'&entry.1=' + email +
'&entry.0=' + content
});
};
return myService;
}]);
<强>单元测试强>
'use strict';
describe('Controller: QuickMessageCtrl', function() {
var $httpBackend, $rootScope, $controller, scope, apiUrl;
beforeEach(module('myApp'));
beforeEach(inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
apiUrl = $injector.get('apiUrl');
$httpBackend.expectJSONP(
'https://docs.google.com/forms/d/MyFormKey/formResponse?'+
'entry.3=test'+
'&entry.1=test@test.com'+
'&entry.0=thisIsContent'
).respond(200, {});
$rootScope = $injector.get('$rootScope');
scope = $rootScope.$new();
$controller = $injector.get('$controller');
$controller('QuickMessageCtrl', { $scope: scope });
}));
describe('form submit', function() {
var changeStateSpy;
beforeEach(function() {
scope.quickMessage.name = 'test';
scope.quickMessage.content = 'thisIsContent';
scope.quickMessage.email ='test@test.com';
});
afterEach(function(){
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should set submitting indicators on submit', function() {
scope.postQuickMessageToGoogle();
expect(scope.quickMessageButtonText).toBe('');
$httpBackend.flush();
});
});
});